java引用类型变量有哪些,java – 有没有办法引用当前类型的类型变量?

要建立在

StriplingWarrior’s answer上,我认为需要以下模式(这是一个分层流利的构建器API的方法)。

首先,一个基本的抽象类(或接口),其中列出了用于返回扩展类的实例的运行时类型的合同:

/**

* @param The runtime type of the implementor.

*/

abstract class SelfTyped> {

/**

* @return This instance.

*/

abstract SELF self();

}

所有中间扩展类必须是抽象的并且保持递归类型参数SELF:

public abstract class MyBaseClass>

extends SelfTyped {

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 mbc2 = new MyBaseClass().baseMethod();

//wrong: no way to correctly declare the type, as its parameter is recursive!

MyBaseClass> mbc3 =

new MyBaseClass>().baseMethod();

这就是我把这些课程称为“中间”的原因,这就是为什么他们都应该被标记为抽象的。为了关闭循环并使用模式,需要“叶”类,它用自己的类型解析继承类型参数SELF并实现self()。他们也应该标记为最终,以避免违约:

public final class MyLeafClass extends MyBaseClass {

@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中的curiously recurring template pattern的实现。这种模式本身并不安全,只能用于内部API的内部工作。原因是不能保证上述示例中的类型参数SELF实际上将被解析为正确的运行时类型。例如:

public final class EvilLeafClass extends MyBaseClass {

@Override

AnotherLeafClass self() {

return getSomeOtherInstanceFromWhoKnowsWhere();

}

}

此示例在模式中显示两个孔:

> EvilLeafClass可以“撒谎”,并将任何其他类型的扩展MyBaseClass替换为SELF。

>独立于此,不能保证self()将实际返回这个,这可能是也可能不是一个问题,这取决于在基本逻辑中使用状态。

由于这些原因,这种模式很可能被滥用或滥用。为了防止这种情况,不允许任何涉及的类被公开扩展 – 请注意我使用MyBaseClass中的package-private构造函数,它替换隐式的公共构造函数:

MyBaseClass() { }

如果可能的话,保持self()包私有,所以它不会增加噪音和混乱的公共API。不幸的是,只有SelfTyped是一个抽象类,这是因为接口方法是隐式公开的。

作为zhong.j.yu points out在评论中,对SELF的约束可能会被删除,因为它最终不能保证“self type”:

abstract class SelfTyped {

abstract SELF self();

}

Yu建议仅依赖合同,避免来自非直观递归约束的任何混淆或虚假的安全感。就个人而言,我喜欢离开绑定,因为SELF扩展了SelfTyped< SELF>代表Java中最近可能的self类型表达式。但是,俞先生的观点肯定与Comparable规定的先例相一致。

结论

这是一个值得的模式,允许对您的构建器API进行流畅和表达性的调用。我在认真的工作中使用了几次,最引人注目的是编写了一个自定义查询构建器框架,它允许调用网站如下所示:

List foos = QueryBuilder.make(context, Foo.class)

.where()

.equals(DBPaths.from_Foo().to_FooParent().endAt_FooParentId(), parentId)

.or()

.lessThanOrEqual(DBPaths.from_Foo().endAt_StartDate(), now)

.isNull(DBPaths.from_Foo().endAt_PublishedDate())

.or()

.greaterThan(DBPaths.from_Foo().endAt_EndDate(), now)

.endOr()

.or()

.isNull(DBPaths.from_Foo().endAt_EndDate())

.endOr()

.endOr()

.or()

.lessThanOrEqual(DBPaths.from_Foo().endAt_EndDate(), now)

.isNull(DBPaths.from_Foo().endAt_ExpiredDate())

.endOr()

.endWhere()

.havingEvery()

.equals(DBPaths.from_Foo().to_FooChild().endAt_FooChildId(), childId)

.endHaving()

.orderBy(DBPaths.from_Foo().endAt_ExpiredDate(), true)

.limit(50)

.offset(5)

.getResults();

关键是QueryBuilder不仅仅是一个平面的实现,而是从构建器类的复杂层次结构延伸出来的“叶”。帮助者使用相同的模式,例如Where,Having等等,所有这些都需要共享重要的代码。

底线,请仔细看看在实施之前是否真的有必要 – 如果你这样做,不要让它公开扩展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值