Method accepting two different types as parameter

前端 未结 8 1836
無奈伤痛
無奈伤痛 2020-12-13 00:39

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

8条回答
  •  粉色の甜心
    2020-12-13 01:04

    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.

提交回复
热议问题