目前,我已经定义了一个空接口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.
}
没有办法在java类型系统中强制执行这一点。因此,您将留下:
- 反射
- 定制静态分析
- 代码审查&开发人员教育
我会远离反射和静态分析。您还没有说明要用这个方法解决什么问题,因此很难给出任何替代方法。
我同意@fge的观点,这听起来像是XY问题,但我认为您可能能够在编译时得到一些工作。
你想对一个类型的每个方法都有一个需求,但是Java只允许你指定存在一些方法满足一个类型的一些需求,所以你将不得不重构U
和V
。
在设置中,我让X
指定任何实现者必须提供返回Y
后代的方法。我还指定了Y
是一个抽象类。
interface X {
Y getY();
}
abstract class Y {
}
然后,我看了你的接口U
和V
,以及它们的方法U#getA()
, U#getB(String)
, V#getC(Integer)
, V#getD()
。所有这些方法都可以放在它们自己的类中。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() {
...
}
}
现在,任何实现X的东西都必须提供y。现在的问题是UA
, UB
, VC
和VD
可以提供其他方法。您已经说过,您只希望它们提供返回Y
的方法。为了解决这个问题,您可以用final
具体类替换X,该类只提供一个您可以控制的构造函数。
将X
替换为YFactory
(代码中的所有地方)
interface YFactory {
Y getY();
}
现在,将X指定为只有一个构造函数的具体类:
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
都只有返回Y
的方法。