10

可能有点难以描述。但是,我会尝试的;)

遵循流利的风格,一个类的方法通常返回类实例本身(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

}

但是,当在这个扩展类上执行另一个继承步骤时,我在尝试定义方法的通用返回类型(在上层类中)和类描述本身时遇到了麻烦,例如,在 super-super 中的方法class 不会返回扩展类的类型,而是返回超类的类型。然而,我的意图是这些流畅的风格方法应该总是返回当前类的类型(而不是上层类)。

那么是否可以通过使用泛型来定义解决方案?

PS:我知道,一个简单的解决方法可能是覆盖扩展类中的所有这些方法并将它们转换为当前类型。但是,我对更优雅的解决方案感兴趣;)

4

4 回答 4

4

你可以试试:

class A<T> { }

class B<T extends A<? super T>> extends A<T> { }

class C extends B<C> { }
于 2012-07-20T15:40:58.140 回答
1

你可以这样做:

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
于 2012-06-21T17:46:21.967 回答
1

一般不可能“返回当前类的类型”。

即使您在上面发布的代码也不安全:public class C extends A<B>是合法的,但是调用doSomething()它,期待 a B,会崩溃。

于 2012-06-21T18:15:50.043 回答
0

使用委托来实现可扩展的流畅接口。优点:没有演员表。缺点:冗长。

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;
    }
}
于 2012-06-22T18:05:13.440 回答