I am writing a method that should accept as its parameter an object of one of two types which do not share a parent type other than Object. For example, the types are Dreams
You could use an interface and adapt your types to it.
Interface:
public interface Crushable {
public void crush();
}
Example invocation:
public class Crusher {
public static void crush(Crushable crushable) {
crushable.crush();
}
}
Example adapter factory method:
public final class Dreams {
public static Crushable asCrushable(final Dream dream) {
class DreamCrusher implements Crushable {
@Override
public void crush() {
dream.crush();
}
}
return new DreamCrusher();
}
private Dreams() {}
}
The consumer code looks like this:
Dream dream = new Dream();
Crushable crushable = Dreams.asCrushable(dream);
Crusher.crush(crushable);
If you have many types to adapt, you could consider reflection. Here is an (unoptimized) adapter factory that uses the Proxy type:
public final class Crushables {
private static final Class>[] INTERFACES = { Crushable.class };
public static Crushable adapt(final Object crushable) {
class Handler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return crushable.getClass()
.getMethod(method.getName(), method.getParameterTypes())
.invoke(crushable, args);
}
}
ClassLoader loader = Thread.currentThread()
.getContextClassLoader();
return (Crushable) Proxy.newProxyInstance(loader, INTERFACES, new Handler());
}
private Crushables() {}
}
To the API consumer, this isn't that ugly:
Dream dream = new Dream();
Crushable crushable = Crushables.adapt(dream);
Crusher.crush(crushable);
However, as is usual with reflection, you sacrifice compile-time type checking.