>这可能有点难以描述。但是,我会尝试;)
遵循流畅的样式,类的方法返回类实例本身(this)是很常见的。
public class A {
public A doSomething() {
// do something here
return this;
}
}
当扩展这样一个流畅的样式类时,可以在第一个继承步骤中通过泛型类型将返回类型强制转换为超类中的此泛型类型,从而相当容易地做到这一点。
public class A<T extends A<T>> {
public T doSomething() {
// do something here
return (T) this;
}
}
public class B extends A<B> {
// an extended class of class A
}
但是,当在这个扩展类上执行另一个继承步骤时,我在尝试定义方法的泛型返回类型(在上层类中)和类描述本身时遇到了麻烦,例如,超超类中的方法不会返回扩展类的类型,而是返回超类的类型。但是,我的意图是这些流畅的样式方法应始终返回当前类的类型(而不是上层类)。
那么,是否有可能通过使用泛型来定义解决方案呢?
PS:我知道,一个简单的解决方法可能是覆盖扩展类中的所有这些方法并将它们转换为当前类型。但是,我对更优雅的解决方案感兴趣;)
你可以试试:
class A<T> { }
class B<T extends A<? super T>> extends A<T> { }
class C extends B<C> { }
你可以做这样的事情:
public class TestFluent<T extends TestFluent<?>> {
public T get() {
return (T) this;
}
public static void main(final String[] args) {
TestFluent2<TestFluent2<?>> f2 = new TestFluent2<TestFluent2<?>>();
TestFluent2<?> result2 = f2.get();
TestFluent3<TestFluent3<?>> t3 = new TestFluent3<TestFluent3<?>>();
TestFluent3<?> result3 = t3.get();
System.out.println(result2);
System.out.println(result3);
}
}
class TestFluent2<T extends TestFluent2<?>> extends TestFluent<T> {
}
class TestFluent3<T extends TestFluent3<?>> extends TestFluent2<T> {
}
这将返回:
TestFluent2@7919298d
TestFluent3@62f72617
通常不可能"返回当前类的类型"。
甚至您上面发布的代码也是不安全的:public class C extends A<B>
是合法的,但是调用doSomething()
,期望B
,会崩溃。
使用委派实现可扩展的流畅接口。 优点:没有演员表。 缺点:冗长。
public interface FluentGranddad< C extends FluentGranddad< C > > {
C appendFoo( Foo foo );
}
public interface FluentDad< C extends FluentDad< C > > extends FluentGranddad< C > {
C appendBar( Bar b );
}
public interface FluentKid< C extends FluentKid< C > > extends FluentDad< C > {
C appendSplat( Splat s );
}
public class Babbler implements FluentKid< Babbler > {
FluentDad< ? > dad;
public Babbler( FluentDad< ? > dad ) {
this.dad = dad;
}
// delegation methods
@Override public Babbler appendFoo( Foo foo ) {
dad.appendFoo( foo );
return this;
}
@Override public Babbler appendBar( Bar bar ) {
dad.appendBar( bar );
return this;
}
// example instance method
@Override public Babbler appendSplat( Splat s ) {
dad.getState().append( s.toString() );
return this;
}
}