【问题标题】:Implementing generic interfaces in Java with common code使用通用代码在 Java 中实现通用接口
【发布时间】:2012-09-06 07:26:00
【问题描述】:

假设我有如下接口:

public interface UnaryFunction<Ret, Arg> {
    public Ret invoke(Arg arg);
}

public interface BinaryFunction<Ret, Arg1, Arg2> {
    public Ret invoke(Arg1 arg, Arg2 arg);
}

现在假设我有一个像这样的包装类:

public class ConstructorWrapper<Ret> {
    // Wrapper for a java.lang.reflect.Constructor
    private final Constructor<Ret> constructor;

    // Try blocks in the following elided for brevity

    // Trying to implement UnaryFunction<Ret, Arg> with this
    public <Arg> Ret invoke(Arg arg) { return constructor.newInstance(arg); }

    // Trying to implement BinaryFunction<Ret, Arg1, Arg2> with this
    public <Arg1, Arg2> Ret invoke(Arg1 arg1, Arg2 arg2) { return constructor.newInstance(arg1, arg2); }
}

如何更改此设置,以便声明 ConstructorWrapper 实现 UnaryFunctionBinaryFunction?更好的是,我该如何做到这一点,以便传入一个单参数构造函数会产生一个仅实现 UnaryFunctionConstructorWrapper 对象(或其中的子类),而传入一个双参数构造函数会产生一个 ConstructorWrapper 对象仅实现BinaryFunction(即,因此您不会在预期BinaryFunction 的地方传入一元构造函数)?最好尽量少重复?

【问题讨论】:

    标签: java generics reflection interface


    【解决方案1】:

    有什么问题:

    public class ConstructorWrapper<Ret, Arg, Arg1, Arg2>
      implements UnaryFunction<Ret, Arg>, BinaryFunction<Ret, Arg1, Arg2>
    

    让一个类同时提供两种 API 有什么问题?

    如果两者都没有,请制作两个包装器。如果您想减少代码重复,它们可以有一个抽象超类。但是如果你想要类型安全,包装类应该实现接口!

    【讨论】:

    • Arg、Arg1 和 Arg2 只是类型参数。它们不是具体类型。
    • ConstructorWrapper&lt;Ret&gt; 应该是 ConstructorWrapper&lt;Ret, Arg1, Arg2&gt; 否则存在编译问题。
    • 当然。谢谢。请注意,如果需要,您可以将 ArgArg1 设置为同一类型。关键是,我觉得我还没有完全理解这个问题。
    【解决方案2】:

    我该如何做到这一点,以便传入一个单参数构造函数会导致一个仅实现 UnaryFunction 的 ConstructorWrapper 对象(或其中的子类),而传入一个双参数构造函数会导致一个仅实现 BinaryFunction 的 ConstructorWrapper 对象。

    这只有在你有两个不同的来创建这些ConstructorWrapper对象时才有可能,例如

    class ConstructorWrapperUnary<Ret, Arg1> extends ConstructorWrapper {...}
    
    class ConstructorWrapperBinary<Ret, Arg1, Arg2> extends ConstructorWrapper {...}
    

    【讨论】:

      【解决方案3】:

      改用工厂:

      public class ConstructorFactory
      {
          public static <Ret, Arg> Ret invoke(UnaryFunction<Ret, Arg> f, Arg arg)
          {
              return f.invoke(arg);
          }
      
          public static <Ret, Arg1, Arg2> Ret invoke(BinaryFunction<Ret, Arg1, Arg2> f, Arg1 arg1, Arg2 arg2)
          {
              return f.invoke(arg1, arg2);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多