J.S*_*eve 11 java generics inheritance types casting
我有一个构建器类,它从大多数方法返回以允许菊花链.为了使这个工作与子类,我希望父方法返回子的实例,以便子方法可用于链到最后.
public class BaseBuilder<T extends BaseBuilder<T>> {
public T buildSomething() {
doSomeWork();
/* OPTION #1: */ return this; // "Type mismatch: cannot convert from BaseBuilder<T> to T"
/* OPTION #2: */ return T.this; // "Type mismatch: cannot convert from BaseBuilder<T> to T"
/* OPTION #3: */ return (T) this; // "Type safety: Unchecked cast from SqlBuilder<T> to T"
}
}
public class ChildBuilder extends BaseBuilder<ChildBuilder> {}
Run Code Online (Sandbox Code Playgroud)
选项#1和#2导致编译错误,选项#3导致警告(尽管可以抑制@SuppressWarnings("unchecked")
).这里有更好的方法吗?我怎样才能安全地将Basebuilder投降给Childbuilder?
声明ChildBuilder extends BaseBuilder<ChildBuilder>
以某种方式表明代码气味并且似乎违反DRY.在这个例子BaseBuilder
中,只能使用ChildBuilder
其他参数进行参数化,因此它应该是多余的.
我宁愿重新考虑我是否真的想过度构建这个,我会尝试将所有来自子构建器的方法放入BaseBuilder
.然后我可以简单地this
从支持链接的所有方法返回.
如果我仍然认为通过将特定的构建器方法组分成它们自己的类来获益,那么我会优先考虑组合,因为不推荐仅为代码重用应用继承.
假设我们有两个子类BaseBuilder
:
class BuilderA extends BaseBuilder<BuilderA> {
BuilderA buildSomethingA() { return this; }
}
class BuilderB extends BaseBuilder<BuilderB> {
BuilderB buildSomethingB() { return this; }
}
Run Code Online (Sandbox Code Playgroud)
如果需要连锁buildSomethingA
和buildSomethingB
喜欢怎么办?
builder.buildSomething().buildSomethingA().buildSomethingB();
Run Code Online (Sandbox Code Playgroud)
如果不将子类方法移动到BaseBuilder
; 我们将无法做到; 但是想象一下BuilderC
,这些方法也没有意义,不应该继承BaseBuilder
.
如果我们仍然将这两个方法移动到超类,下一次将其他三个方法移动到下一个时间......我们最终会得到一个超类,它负责整个层次结构的90%的职责,并且有很多代码,例如:
if ((this instanceof BuilderB) && !flag1 && flag2) {
...
} else if ((this instanceof BuilderC) && flag1 && !flag2 && thing != null) {
...
} else if ...
Run Code Online (Sandbox Code Playgroud)
我更喜欢的解决方案是DSL,如:
builder.buildSomething1().buildSomething2()
.builderA()
.buildSomethingA1().buildSomethingA2()
.end()
.buildSomething3()
.builderB()
.buildSomethingB()
.end();
Run Code Online (Sandbox Code Playgroud)
这里end()
返回builder
实例,以便您可以链接更多方法或启动新的子构建器.
这种方式(子)构建器可以从它们需要的任何东西继承(否则它们只能扩展BaseBuilder
),并且可以拥有自己有意义的层次结构或组合.
归档时间: |
|
查看次数: |
2327 次 |
最近记录: |