Java Fluent接口-返回最具体的返回类型 情况:
我有一个类层次结构,看起来有点像这样。请注意,我的文字看起来并不是这样的,我只是这样写的,以使它更短,在我看来,更清晰Java Fluent接口-返回最具体的返回类型 情况:,java,design-patterns,fluent,return-type,Java,Design Patterns,Fluent,Return Type,我有一个类层次结构,看起来有点像这样。请注意,我的文字看起来并不是这样的,我只是这样写的,以使它更短,在我看来,更清晰 public abstract BaseClass { private Alpha a; private Beta b; public Alpha getAlpha() { return a; } public Beta getBeta() { return b; } public BaseClass setAlpha(Alpha a)
public abstract BaseClass {
private Alpha a;
private Beta b;
public Alpha getAlpha() { return a; }
public Beta getBeta() { return b; }
public BaseClass setAlpha(Alpha a) { this.a = a; return this; }
public BaseClass setBeta(Beta b) { this.b = b; return this; }
}
public Foo extends BaseClass {
@Override
public Foo setBeta(Beta b) {
super.setBeta(b);
doSomethingElse();
return this;
}
public Gamma getGamma() { return g; }
public Foo setGamma(Gamma g) { this.g = g; return this; }
}
public Bar extends BaseClass {
private Omega o;
@Override
public Bar setAlpha(Alpha a) {
super.setAlpha();
doSomethingElse();
return this;
}
public Omega getOmega() { return o; }
public Bar setOmega(Omega o) { this.o = o; return this; }
}
问题是:
以上列出的方法还有很多。请注意,它们不符合相同的接口。使用Foo
和Bar
并需要调用setGamma
和setOmega
的类始终可以访问最特定的类。但是,这些类还需要调用setAlpha
和setBeta
。但是,这些方法不会返回正确的类型,除非我重写它们
选项:
基类的每个方法
,只是为了更改返回类型
- 似乎有很多不必要的代码
BaseClass
中声明每个方法,如setGamma
和setOmega
抽象。这可能行得通,但我必须为那些毫无意义的类定义它抛出新的UnsupportedOperationException()
异常
someBar.setOmega().setAlpha()
但不someBar.setAlpha().setOmega()
注意:这种情况与此不同:因为它不是真正的泛型问题。正如@chrylis在注释中指出的,您可以泛型化
基类
:
public abstract class BaseClass<T extends BaseClass> {
private Alpha a;
private Beta b;
public Alpha getAlpha() {
return a;
}
public Beta getBeta() {
return b;
}
@SuppressWarnings("unchecked")
public T setAlpha(Alpha a) {
this.a = a;
return (T) this;
}
@SuppressWarnings("unchecked")
public T setBeta(Beta b) {
this.b = b;
return (T) this;
}
}
公共抽象类基类{
私人阿尔法a;
私人Beta b;
公共Alpha getAlpha(){
返回a;
}
公共Beta getBeta(){
返回b;
}
@抑制警告(“未选中”)
公共T组α(αa){
这个a=a;
返回(T)这个;
}
@抑制警告(“未选中”)
公共T-setBeta(Beta b){
这个.b=b;
返回(T)这个;
}
}
并延长如下:
傅:
公共类Foo扩展了基类{
私人伽马g;
@凌驾
公共食品展(Beta b){
super.setBeta(b);
doSomethingElse();
归还这个;
}
私有void doSomethingElse(){}
公共Gamma getGamma(){
返回g;
}
公共食品设定伽马(伽马g){
这个.g=g;
归还这个;
}
}
酒吧:
公共类栏扩展了基类{
私人欧米茄o;
@凌驾
公共酒吧设置Alpha(Alpha a){
super.setAlpha(a);
doSomethingElse();
归还这个;
}
私有void doSomethingElse(){}
公共Omega getOmega(){
返回o;
}
公共酒吧设置欧米茄(欧米茄o){
这个。o=o;
归还这个;
}
}
这引入了两个未经检查的强制转换警告,我抑制了它们。它可以编译,但我还没有试着用它做任何事情。如果您需要在
setBeta
或setAlpha
期间调用doSomethingElse()
,您没有选择。我想您可以将基类
泛化,并让setAlpha/Beta
返回
,但我今晚没时间签名,我有点喜欢这个。我看到的一个问题是,从技术上讲,您可以执行公共类Baz扩展基类
,这将导致类异常
s。当然我永远不会这么做,但这会让设计容易犯这样愚蠢的错误。是的,不可否认它有点脆弱。如果你的答案是选项6,如果你设计这个系统,你会选择哪个选项?我可能会这样做。它并不完美,但我认为它比其他选择要好。如果你要走这条路,就用基类泛型参数
代替``。我还建议只以可控的方式使用这种风格,而不是将其应用到整个体系结构中,因为由于泛型问题,Java确实不能很好地处理流畅的接口。
public class Foo extends BaseClass<Foo> {
private Gamma g;
@Override
public Foo setBeta(Beta b) {
super.setBeta(b);
doSomethingElse();
return this;
}
private void doSomethingElse() { }
public Gamma getGamma() {
return g;
}
public Foo setGamma(Gamma g) {
this.g = g;
return this;
}
}
public class Bar extends BaseClass<Bar> {
private Omega o;
@Override
public Bar setAlpha(Alpha a) {
super.setAlpha(a);
doSomethingElse();
return this;
}
private void doSomethingElse() { }
public Omega getOmega() {
return o;
}
public Bar setOmega(Omega o) {
this.o = o;
return this;
}
}