一个Java接口,通过设计强制实现其未知方法的输出类型?

时间:2015-07-15 06:02:12

标签: java generics types interface architecture

目前,我已经定义了一个 empty 接口X,它由其他一些接口实现(只是为了在其他地方识别它们)。

实现X的所有接口都可以提供他们希望的公共方法,但是我想通过设计/体系结构来强制执行,所有这些接口(再次注意它们对X是未知的)将返回派生的类型来自同一个抽象类Y。

我用他们的方式在Java中做到这一点吗?

在下面的示例中,X应该强制只有U和V返回从Y派生的类型。

public interface X {
    // I'm empty at present.
}

public interface U extends X {
    public A getA();
    public B getB(String bIn);
}

public interface V extends X {
    public C getC(Integer cIn);
    public D getD(); // Compile should fail!
}

public class A extends Y {
}

public class B extends Y {
}

public class C extends Y {
}

public class D {
    // D does *not* extend Y.
}

2 个答案:

答案 0 :(得分:0)

无法使用java类型系统强制执行此操作。因此,您将留下:

  • 反射
  • 自定义静态分析
  • 代码评论&开发者教育

我会远离反射和静态分析。你没有说过你试图用这个解决什么问题,所以很难给出任何替代方法。

答案 1 :(得分:0)

我同意@fge这听起来像是一个XY问题,但我认为你可以在编译时得到一些东西。

您希望对类型的每个方法提出要求,但Java只允许您指定存在满足某些类型要求的方法,因此您必须重构U和{{1} }。

在设置中,我使V指定任何实现者必须提供返回X后代的方法。我还指出Y是一个抽象类。

Y

然后,我查看了您的界面interface X { Y getY(); } abstract class Y { } U及其方法VU#getA()U#getB(String)V#getC(Integer)。所有这些方法都可以放在自己的类中。

V#getD()

现在,任何实现X的东西都必须提供Y.现在的问题是class UA implements X { public A getY() { ... } } class UB implements X { private final String s; public UB(String s) { this.s = s; } public B getY() { ... } } class VC implements X { private final Integer integer; public VC(Integer integer) { this.integer = integer; } public C getY() { ... } } // COMPILE-TIME ERROR class VD implements X { public D getY() { ... } } UAUBVC可以提供其他方法。您已经说过,您只希望他们提供返回VD的方法。要解决这个问题,你可以用一个Y具体类替换X,它只提供你控制的一个构造函数。

final替换为X(代码中的任何位置)

YFactory

现在,将X指定为只有一个构造函数的具体类:

interface YFactory {
    Y getY();
}

所有在一起:

final class X {
    private final YFactory yFactory;

    public X(YFactory yFactory) {
        this.yFactory = yFactory;
    }

    public Y getY() {
        return yFactory.getY();
    }
}

现在您知道任何final class X { private final YFactory yFactory; public X(YFactory yFactory) { this.yFactory = yFactory; } public Y getY() { return yFactory.getY(); } } abstract class Y { } interface YFactory { Y getY(); } class A extends Y { } class B extends Y { } class C extends Y { } class D { // D does *not* extend Y. } class UA implements YFactory { public A getY() { return null; } } class UB implements YFactory { private final String s; public UB(String s) { this.s = s; } public B getY() { return null; } } class VC implements YFactory { private final Integer integer; public VC(Integer integer) { this.integer = integer; } public C getY() { return null; } } class VD implements YFactory { public D getY() { return null; } } 只有返回X的方法。