假设你是创建一个函数以返回当前类型的实例。有没有办法让类型变量 T 引用精确的子类型(因此 T 应该引用 B 类中的 B)?
class A { <T extends A> void foo(); } class B extends A { @Override T foo(); }
为了构建 StriplingWarrior 的响应,需要以下设计(分层流畅构建器 API 的公式):
首先,一个抽象基类(或接口),用于建立用于检索扩展类的实例的运行时类型的契约:
/** * @param <SELF> The runtime type of the implementer. */ abstract class SelfTyped<SELF extends SelfTyped<SELF>> { /** * @return This instance. */ abstract SELF self(); }
中间扩展类必须是抽象的并维护递归类型参数 SELF:
public abstract class MyBaseClass<SELF extends MyBaseClass<SELF>> extends SelfTyped<SELF> { MyBaseClass() { } public SELF baseMethod() { //logic return self(); } }
进一步派生的类可以遵循相同的图案。但是,如果不使用原始类型或通配符(这会破坏该模式的目的),这些类都不能直接用作变量类型。例如(如果 MyClass 不是抽象的):
//wrong: raw type warning MyBaseClass mbc = new MyBaseClass().baseMethod(); //wrong: type argument is not within the bounds of SELF MyBaseClass<MyBaseClass> mbc2 = new MyBaseClass<MyBaseClass>().baseMethod(); //wrong: no way to correctly declare the type, as its parameter is recursive! MyBaseClass<MyBaseClass<MyBaseClass>> mbc3 = new MyBaseClass<MyBaseClass<MyBaseClass>>().baseMethod();
这就是为什么这些类被称为“中间类”,以及为什么它们都应该被声明为抽象的。 “叶”类需要完成循环并使用该模式,该模式解析继承的类型参数 SELF 及其类型并实现 self()。为了防止破坏契约,它们还应该被标记为final:
public final class MyLeafClass extends MyBaseClass<MyLeafClass> { @Override MyLeafClass self() { return this; } public MyLeafClass leafMethod() { //logic return self(); //could also just return this } }
使用这样的类使得模式可用:
MyLeafClass mlc = new MyLeafClass().baseMethod().leafMethod(); AnotherLeafClass alc = new AnotherLeafClass().baseMethod().anotherLeafMethod();
这样做的主要优点是方法调用可以在类层次结构中上下链接,同时保持相同的特定返回类型。
以上是如何在 Java 中使用类型变量引用当前类型?的详细内容。更多信息请关注PHP中文网其他相关文章!