[英]How can I get subclasses to return their own type?
这里我们有多个使用相关语法的自定义查询-DSL。 我正在创建一个AbstractBuilder
以便所有的通用性都可以写在一个地方。 问题是这会导致方法链接问题。 当我尝试从一个方法链接到AbstractBuilder
这样一个子类时,它不能在没有强制转换的情况下工作。
有了这些课程:
class AbstractBuilder{
protected final StringBuilder bldr = new StringBuilder();
AbstractBuilder addValue( String name, String value ){
bldr.append( name ).append( '=' ).append( value )append( ',' );
return this;
}
String toString(){
return bldr.toString();
}
}
class IntBuilder extends AbstractBuilder{
IntBuilder addValue( String name, int value ){
bldr.append( name ).append( '=' ).append( value )append( ',' );
return this;
}
}
这有效
new IntBuilder().addValue( "age", 12 ).addValue( "name", "Bruce" ).toString();` but `new IntBuilder().addValue( "name", "Bruce" ).addValue( "age", 12 ).toString();
除非你做一个丑陋的演员,否则不会:
((IntBuilder) (new IntBuilder().addValue( "name", "Bruce" ))).addValue( "age", 12 ).toString();
现在我想我可以覆盖每个方法并通过对父母的调用来实现它们(通过super.addValue( name, value );
),但这真的很难看。
我怎么能让每个方法都返回当前的类而不是它所定义的类?
你可以使用泛型来实现这一点。
class BaseBuilder<B extends BaseBuilder>{
protected final StringBuilder bldr = new StringBuilder();
private Class<B> builderImplementationClass;
protected BaseBuilder( Class<B> builderImpl ){
builderImplementationClass = builderImpl;
if( this.getClass() != builderImpl )
throw new IllegalStateException( "Should match." );
}
B addValue( String name, String value ){
bldr.append( name ).append( '=' ).append( value )append( ',' );
return builderImplementationClass.cast( this );
}
String toString(){
return bldr.toString();
}
}
class IntBuilder extends AbstractBuilder<IntBuilder>{
public IntBuilder(){
super( IntBuilder.class );
}
IntBuilder addValue( String name, int value ){
bldr.append( name ).append( '=' ).append( value )append( ',' );
return this;
}
}
基本上,您使所有方法返回类型B
的值,并确保将B
设置为当前的实现
ArtB的解决方案很好,但您可以通过以下方式使其更简单:
private static class AbstractBuilder <T extends AbstractBuilder<T>> {
protected StringBuilder bldr = new StringBuilder();
public T addValue( String name, String value ){
bldr.append( name ).append( '=' ).append( value ).append(',');
@SuppressWarnings("unchecked")
T result = (T)this;
return result;
}
public String toString(){
return bldr.toString();
}
}
private static class IntBuilder extends AbstractBuilder<IntBuilder> {
public IntBuilder addValue( String name, int value ){
bldr.append( name ).append( '=' ).append( value ).append(',');
return this;
}
}
注意我还修复了两个私有StringBuilder变量的bug,这几乎肯定不是你想要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.