我的问题是在Method chaining + inheritance don’t play well together?的上下文中。
但是不幸的是,方法链接的所有示例/答案都使用单级继承。
我的用例涉及例如多个层次的继承

abstract class PetBuilder{...}
class  DogBuilder extends PetBuilder{..}
class DogType1Builder extends DogBuilder {...}

为了构造一个Dog对象,我将使用DogBuilder或DogType1Builder

如何在上述用例中使用getThis技巧?

我想使用构建器模式来构建复杂的Dog对象(“狗对象模型”)”
DogType1将具有一些附加属性。

所以使用上述类的getThis Trick声明将变得像
abstract class PetBuilder<T extends PetBuilder<T>>
class DogBuilder<T extends DogBuilder<T>> extends PetBuilder<DogBuilder<T>>
class DogType1Builder extends DogBuilder<DogType1Builder>

现在,这产生了两个问题

1.'DogBuilder'中的builder方法看起来像
public T someMethodInDog(String dogName) {
..
return (T)this; ///i dont want type casting and i cant use getThis Trick Here (compiler reports error for conversion from DogBuilder to T)
}

2.由于DogBuilder已被参数化,因此要创建“DogBuilder”实例,我将不得不使用
DogBuilder<DogBuilder> builder=new DogBuilder(); //passing <DogBuilder> type ...real pain

有没有更好的办法?

最佳答案

问题的根源是类设计问题:,您正在尝试从具体的类继承,这几乎总是一个错误,并且(以您的情况为准)必然会导致许多问题。为了坚持引用的线程中给出的示例,您不应该实例化Dog,因为在这样的Universe中,除了Dog s之外,通常不存在Pet s-仅Poodle s,NewFoundland s,Spaniel s等。 ,getThis不应在中级(抽象)类中实现,而只能在(具体)叶类中实现。并且在所有中级抽象类中,您只应引用通用类型参数T,而不是实际的类名。

这是按照上述规则重写的the answer to the referred thread中的示例:

public class TestClass {

  static abstract class Pet <T extends Pet<T>> {
    private String name;

    protected abstract T getThis();

    public T setName(String name) {
      this.name = name;
      return getThis(); }
  }

  static class Cat extends Pet<Cat> {
    @Override protected Cat getThis() { return this; }

    public Cat catchMice() {
      System.out.println("I caught a mouse!");
      return getThis();
    }
  }

  // Dog is abstract - only concrete dog breeds can be instantiated
  static abstract class Dog<T extends Dog<T>> extends Pet<T> {
    // getThis is not implemented here - only in concrete subclasses

    // Return the concrete dog breed, not Dog in general
    public T catchFrisbee() {
      System.out.println("I caught a frisbee!");
      return getThis();
    }
  }

  static class Poodle extends Dog<Poodle> {
    @Override protected Poodle getThis() { return this; }

    public Poodle sleep() {
      System.out.println("I am sleeping!");
      return getThis();
    }
  }

  static class NewFoundland extends Dog<NewFoundland> {
    @Override protected NewFoundland getThis() { return this; }

    public NewFoundland swim() {
      System.out.println("I am swimming!");
      return getThis();
    }
  }

  public static void main(String[] args) {
    Cat c = new Cat();
    c.setName("Morris").catchMice();
    Poodle d = new Poodle();
    d.setName("Snoopy").catchFrisbee().sleep();
    NewFoundland f = new NewFoundland();
    f.setName("Snoopy").swim().catchFrisbee();
  }
}

10-05 22:11