Multi-typed Parameters

In some cases you want to define a method parameter which is of a certain type (i.e a class or an interface), but also implements another interface.

Start Situation

If the first type is a class, the basic situation looks like (1):

class A { String getMyA(); } interface B { String getMyB(); }

Now you have classes which do combine both of the above (2):

class C extends A implements B { } class D extends A implements B { }

Finally you want to implement the following (3):

class X { static String getAB(/*C or D*/ object) { return object.getMyA() + object.getMyB(); } }

and use it like (4);

// somewhere else C foo = new C(); System.out.println(X.getAB(foo)); D bar = new D(); System.out.println(X.getAB(bar));

Problem is how to implement the C or D type in the getAB() method. Indeed C or D is misleading and too special. What you really want is a type which is both A and B.

Good Solution

This requires at least Java 5. Here you can use a generic type parameter to your help. You only have to change (3) to look like:

class X { static String getAB(T object) { return object.getMyA() + object.getMyB(); } }

This is elegant and requires just a simple change at the place where it ought to be.

Of course this works for non-static methods the same, also for generic classes, and easily extends to more than 2 types. So it’s one of the patterns you should keep in your mental toolbox.

Special Cases

In time-critical code you should keep in mind that each access to object’s methods in getAB() internally uses a cast. What the above code really looks like is similar to:

class X { static String getAB(Object object) { // Java view of code, not your implementation return ((A)object).getMyA() + ((B)object).getMyB(); // Java view of code, not your implementation } }

Casts are (nowadays moderately) expensive, so if you access the object several times in time-critical code you should do the unpacking ourself once:

class X { static String getAB(T object) { A a = object; // here the cast is happening once B b = object; // here the other cast is happening // --- from here only access a and b --- return a.getMyA() + b.getMyB(); } }

Java optimization might be able to figure this out, too, but I’d prefer to be sure.

Bad Solutions

Before Java 5 you had only two options: insert a common base class or extend the method getAB() to accept two parameters.

But if you are using a modern Java implementation: Don’t do this!

Insert a Common Base Class (deprecated)

(1) and (4) above stay the same, but (2) now looks like

class Base extends A implements B { } class C extends Base {} class D extends Base {}

and (3) becomes

class X { static String getAB(Base object) { return object.getMyA() + object.getMyB(); } }

In some cases this might even clarify your class structure, but in other cases this would insert an otherwise useless class or interface making things unnecessarily complex.

Inserting a class can even be impossible. This happens for code from libraries, and also for a very special case I encountered:

enum C implements B { /* ... */} enum D implements B { /* ... */}

Both C and D extend Enum, and I wanted to write a method which only accepts enums implementing the special interface B. Of course you now know how I did it:

public & B> void foo(E e) { // ...

Make the Method Take Two Parameters (deprecated)

(1) and (2) stay the same, (3) becomes

class X { static String getAB(A a, B b) { return a.getMyA() + b.getMyB(); } }

and in (4) you’ll have to duplicate the parameter

// somewhere else C foo = new C(); System.out.println(X.getAB(foo, foo)); D bar = new D(); System.out.println(X.getAB(bar, bar));

This is obviously awkward, but removes the need to change the class structure in cases where this is impossible or not preferable.