16

我有一个父类,它定义了一系列链接器方法(返回“this”的方法)。我想定义多个包含它们自己的链接器方法但也“覆盖”父方法的子类,以便返回子类的实例而不是父类。

我不想在每个子类中重复相同的方法,这就是为什么我有一个包含所有子类共享的方法的父类。谢谢。

class Chain {
  public Chain foo(String s){
    ...
    return this;
  }
}

class ChainChild extends Chain {
  //I don't want to add a "foo" method to each child class
  /*
  public ChildChain foo(String s){
    ...
    return this;
  }
  */

  public ChainChild bar(boolean b){
    ...
    return this;
  }
}

ChainChild child = new ChainChild();
child.foo().bar(); //compile error: foo() returns a "Chain" object which does not define the bar() method. 
4

4 回答 4

14

返回的父类中的方法this仍将返回对子类对象的引用。您只能将其视为父类的对象(除非您强制转换它),但它实际上是其原始类型。

您可以考虑使用这样的泛型:

// This seems a bit too contrived for my liking. Perhaps someone else will have a better idea.
public class Parent<T extends Parent<T>> {
    T foo () {
        return (T) this;
    }
}

public class Child extends Parent<Child> {
    public void bar () {
        Child c = foo();
    }
}
于 2013-02-24T17:17:08.253 回答
12

我已经根据您的需要使用泛型编写了这个示例。

class Parent {
    public <T extends Parent> T foo() {
        return (T)this;
    }
}

class Child extends Parent {

}

class AnotherChild extends Parent {

}

public class Test {
    public static void main(String[] args) {

        Parent p = new Child();
        System.out.println(p);
        Child c = p.foo();
        System.out.println(c);
        //throws ClassCastException here since Child is not AnotherChild
        AnotherChild ac = p.foo();
        System.out.println(ac);
    }
}
于 2013-02-24T17:20:49.607 回答
3

这是对 OldCurmudgeon 方法的改进:

public class Parent<This extends Parent<This>> {

    @SuppressWarnings("unchecked")
    private final This THIS = (This)this;

    public This foo() {
        //...
        return THIS;
    }

    public This bar() {
        //...
        return THIS;
    }    
}

public class Child extends Parent<Child> {

    // you can override super with covariant return type
    @Override
    public Child bar() {
        super.bar();

        return this;
    }
}


Child child = 
new Child()
.foo()
.bar();

改进之处在于只进行一次未经检查的强制转换并将其保存到常量 THIS 中,您可以将其重用为方法链接的返回值。

这消除了每个方法中未经检查的强制转换,并使代码更清晰。

您可以通过返回 Child 而不是 This(协变返回类型)来覆盖 Parent 的方法。

于 2013-05-14T10:23:20.230 回答
0

你可以投它。

ChainChild child = new ChainChild();
((ChainChild) child.foo()).bar();

你可以试试:

public ? extends Chain foo() {
    return this;
}

但我不确定这是否会有所帮助,即使它可以编译。

于 2013-02-24T17:18:58.137 回答