Java 递归通用和Fluent接口

Java 递归通用和Fluent接口,java,generics,fluent-interface,nested-generics,Java,Generics,Fluent Interface,Nested Generics,tl;dr 尝试实现一个层次化的fluent接口,这样我就可以合并节点子类,同时也可以独立类,但是获取类型参数不在其限制范围内 详细信息 我试图找到一个解决方案,这样我就可以创造一些东西,比如: farm .animal() .cat() .meow() .findsHuman() .saysHello() .done() .done()

tl;dr

尝试实现一个层次化的fluent接口,这样我就可以合并节点子类,同时也可以独立类,但是获取类型参数不在其限制范围内

详细信息

我试图找到一个解决方案,这样我就可以创造一些东西,比如:

farm
    .animal()
        .cat()
            .meow()
            .findsHuman()
                .saysHello()
                .done()
            .done()
        .dog()
            .bark()
            .chacesCar()
            .findsHuman()
                .saysHello()
                .done()
            .done()
        .done()
    .human()
        .saysHello()
        .done();
同时也能够做到:

Human human = new Human()
    .saysHello()
我已经接近使用各种策略,但未能获得所描述的灵活性

我当前的尝试使用以下类:

abstract class Base<T extends Base<T>>{

    private T parent;

    Base(){

    }

    Base( T parent ){
        this.parent = parent;
    }

    public T done() throws NullPointerException{
        if ( parent != null ){
            return (T) parent;
        }

        throw new NullPointerException();
    }   
}

class Farm<T extends Base<T>> extends Base{

    private Animal<Farm<T>> animal;
    private Human<Farm<T>> human;

    public Farm(){
        super();
        this.animal = new Animal( this );
        this.human = new Human( this );
    }

    public Animal<Farm> animal(){
        return this.animal;
    }

    public Human<Farm<T>> human(){
        return this.human;
    }
}

class Animal <T extends Base<T>> extends Base{

    private Cat<Animal<T>> cat;
    private Dog<Animal<T>> dog;

    public Animal(){
        super();
        init();
    }

    public Animal( T parent ){
        super( parent );
        init();
    }

    private void init(){
        this.cat = new Cat(this);
        this.dog = new Dog(this);
    }

    public Cat<Animal<T>> cat(){
        return cat;
    }

    public Dog<Animal<T>> dog(){
        return dog;
    }
}

class Human<T extends Base<T>> extends Base{

    public Human<T> saysHello(){
        System.out.println("human says hi");
        return this;
    }
}

class Cat <T extends Base<T>> extends Base{

    private Human<Cat> human;

    public Cat(){
        super();
        init();
    }

    public Cat( T parent ){
        super( parent );
        init();
    }

    private void init(){
        this.human = new Human();
    }

    public Cat<T> meow(){
        System.out.println("cat says meow");
        return this;
    }

    public Human<Cat<T>> findsHuman(){
        return this.human;
    }
}


class Dog <T extends Base<T>> extends Base{

    private Human<Dog> human;

    public Dog(){
        super();
        init();
    }

    public Dog( T parent ){
        super( parent );
        init();
    }

    private void init(){
        this.human = new Human();
    }


    public Dog<T> bark(){
        System.out.println("dog says woof");
        return this;
    }

    public Dog<T> chacesCar(){
        System.out.println("cat drinks milk");
        return this;
    }

    public Human<Dog<T>> findsHuman(){
        return this.human;
    }

}
抽象类基类{
私人T型父母;
Base(){
}
基础(T父级){
this.parent=parent;
}
public T done()抛出NullPointerException{
如果(父项!=null){
返回(T)父级;
}
抛出新的NullPointerException();
}   
}
类场扩展了基{
私人动物;
私人的人;
公共农场(){
超级();
this.animal=新动物(this);
this.human=新人类(this);
}
公共动物{
归还这只动物;
}
公共人权(){
归还这个。人类;
}
}
类动物扩展基础{
私家猫


    • 这是我们在一个项目中所做的:

      public abstract class Parent<T extends Parent<T>> {
      
          /**
           * Get {@code this} casted to its subclass.
           */
          @SuppressWarnings("unchecked")
          protected final T self() {
              return (T) this;
          }
      
          public T foo() {
              // ... some logic
              return self();
          }
      
          // ... other parent methods
      
      }
      
      公共抽象类父类{
      /**
      *将{@code this}转换为其子类。
      */
      @抑制警告(“未选中”)
      受保护的最终T self(){
      返回(T)这个;
      }
      公共图书馆{
      //…有些逻辑
      返回自我();
      }
      //…其他父方法
      }
      

      公共类子级扩展父级{
      公共儿童酒吧(){
      //…有些逻辑
      返回自我();
      }
      //…其他子方法
      }
      

      允许孩子拥有自己的子类是:

      public class Child<T extends Child<T>> extends Parent<T> {
      
          public T bar() {
              // ... some logic
              return self();
          }
      
      }
      
      公共类子级扩展父级{
      公共酒吧(){
      //…有些逻辑
      返回自我();
      }
      }
      
      在这行中:

      class Farm<T extends Base<T>>
      
      类场
      
      编译器将第二个类型参数视为一个具体类。例如,如果您将该行替换为:

      class Farm<T extends Base<Double>>
      
      类场
      
      “Double”是一个具体的类。当编译器扫描它时,它无法分辨T和Double之间的区别,因此将它们都视为具体的类,而不是类型参数。让编译器知道T是类型参数的唯一方法是:

      class Farm<T extends Base<T>, T>
      
      类场
      
      我希望这能回答(或至少是相关的)你的问题

      编辑 这篇文章是在我打字时编辑的,所以我想这个答案不再相关了。

      没有“安全”的方法可以做到这一点,但这应该可以编译:

      class Dog extends Base{
      
       <T extends Dog> T bark(){
          return (T) this;
       } 
      
      }
      
      class Dog扩展了基础{
      树皮{
      返回(T)这个;
      } 
      }
      
      我想到的最好的事情是:

      new Animal()
          .cat()
            .meow()
            .findsHuman()
              .<Cat>done()
            .<Animal>done()
          .dog()
            .bark()
              .findHuman()
                .<Dog>done()
            .done();
      
      新动物()
      .cat()
      .meow()
      .findsHuman()
      .完成
      .完成
      .dog()
      .树皮
      .findHuman()
      .完成
      .完成();
      
      使用以下基类:

      public abstract class Base<T extends Base<T>>{
      
        private Base<?> backRef;
      
        public Base() {}
      
        public Base(Base<?> backRef) {
          this.backRef = backRef;
       }
      
        @SuppressWarnings("unchecked")
          protected T self() {
          return (T)this;
        }
      
        @SuppressWarnings("unchecked")
        public <U extends Base<U>> U done() {
          return (U)backRef;
        }
      }
      
      公共抽象类基类{
      私人基地backRef;
      公共基(){}
      公共基地(基地背景参考){
      this.backRef=backRef;
      }
      @抑制警告(“未选中”)
      受保护的T self(){
      返回(T)这个;
      }
      @抑制警告(“未选中”)
      公共服务{
      返回(U)backRef;
      }
      }
      
      如果将backRef声明为类型T,则不允许使用其他类,因为它们不是彼此的子类,因此必须指定不同的类型,但由于此类型依赖于上下文(一次是它的Cat,一次是它的Dog),因此我看不到传递提示的替代方法

      我找到了一个解决方案:

      new Animal()
          .cat()
            .meow()
            .findsHuman()
              .done()
            .done()
          .dog()
            .bark()
              .findHuman()
                .done()
          .done();
      
      
      
      public abstract class Base<T extends Base<T,P>, P>{
      
        private P backRef;
        public Base() {}
      
        public Base(P backRef) {
          this.backRef = backRef;
        }
      
        @SuppressWarnings("unchecked")
        protected T self() {
          return (T)this;
        }
      
        public P done() {
          return backRef;
       }
      }
      
      新动物()
      .cat()
      .meow()
      .findsHuman()
      .完成
      .完成
      .dog()
      .树皮
      .findHuman()
      .完成
      .完成();
      公共抽象类基{
      私人P backRef;
      公共基(){}
      公共基地(P backRef){
      this.backRef=backRef;
      }
      @抑制警告(“未选中”)
      受保护的T self(){
      返回(T)这个;
      }
      公共政策(已完成){
      返回backRef;
      }
      }
      
      正如有人建议的那样,我们为父级添加了一个附加类型

      现在,基类:

      public final class Cat extends Base<Cat, Animal>{
      
        public Cat() {}
      
        public Cat(Animal backRef) {
          super(backRef);
        }
      
        public Cat meow() {
          System.out.println("Meeeoooww");
          return self();
        }
      
        public Human<Cat> findsHuman() {
          return new Human<Cat>(this);
        }
      }
      
      公共最终类Cat扩展了基本类{
      公共猫(){}
      公猫(动物背景){
      super(backRef);
      }
      公猫喵喵(){
      System.out.println(“meeeooww”);
      返回自我();
      }
      公共人工查找人工(){
      返回新人类(本);
      }
      }
      
      如您所见,Cat明确指定了它应该使用的基本类型。现在对于human,它可以根据上下文更改类型:

      public final class Human<P> extends Base<Human<P>, P> {
      
        public Human() {}
      
        public Human(P backRef) {
          super(backRef);
        }
      
      公共最终类人类

      扩展基础{ 公共人权({} 公共人力资源(P backRef){ super(backRef); }

      }


      Human指定了调用方(猫、狗)在其findHuman()方法中指定的另一个泛型。

      您也可以使用接口,这样您就可以伪造多重继承。有点冗长,但没有危险的强制转换,我觉得这是可以理解的


      定义可用的方法:

      new Animal()
          .cat()
            .meow()
            .findsHuman()
              .done()
            .done()
          .dog()
            .bark()
              .findHuman()
                .done()
          .done();
      
      
      
      public abstract class Base<T extends Base<T,P>, P>{
      
        private P backRef;
        public Base() {}
      
        public Base(P backRef) {
          this.backRef = backRef;
        }
      
        @SuppressWarnings("unchecked")
        protected T self() {
          return (T)this;
        }
      
        public P done() {
          return backRef;
       }
      }
      
      公共界面动画{
      动物();
      }
      公共接口{
      猫(猫);
      }
      公共接口MeowIn{
      猫叫();
      }
      公共接口多金{
      DogOut dog();
      }
      公共接口BarkIn{
      狗吠();
      }
      公共接口ChacesCarIn{
      DogOut chacesCar();
      }
      公共接口FindsHumanIn{
      HumanOut findsHuman();
      }
      公共界面HumanIn{
      HumanOut human();
      }
      公共接口SaysHelloIn{
      HumanOut saysHello();
      }
      公共接口DoneIn{
      T done();
      }
      
      您可能需要在一个接口中有多个方法,但我还没有满足这一需求。例如,如果您必须使用各种
      meow
      s:

      公共接口MeowIn{
      用猫叫唤食物;
      CatOut meowForMilk();
      发出喵喵的叫声()来;
      }
      

      定义
      abstract class Base<T extends Base<T, P>, P>{
      
          private P parent;
      
          Base(){
      
          }
      
          Base( P parent ){
              this.parent = parent;
          }
      
          public P done() throws NullPointerException{
              if ( parent != null ){
                  return parent;
              }
      
              throw new NullPointerException();
          }   
      }
      
      class Farm extends Base<Farm, Object>{
      
          private Animal animal;
          private Human human;
      
          public Farm(){
              super();
              this.animal = new Animal( this );
              this.human = new Human( this );
          }
      
          public Animal animal(){
              return this.animal;
          }
      
          public Human human(){
              return this.human;
          }
      }
      
      class Animal extends Base<Animal, Farm>{
      
          private Cat cat;
          private Dog dog;
      
          public Animal(){
              super();
              init();
          }
      
          public Animal( Farm parent ){
              super( parent );
              init();
          }
      
          private void init(){
              this.cat = new Cat(this);
              this.dog = new Dog(this);
          }
      
          public Cat cat(){
              return cat;
          }
      
          public Dog dog(){
              return dog;
          }
      }
      
      class Human extends Base<Human, Farm>{
      
          public Human() {
      
          }
      
          public Human(Farm farm) {
              super(farm);
          }
      
          public Human saysHello(){
              System.out.println("human says hi");
              return this;
          }
      
      }
      
      class CatOrDog extends Base<Cat, Animal>{
      
          protected Human human;
      
          public CatOrDog(){
              super();
              init(null);
          }
      
          public CatOrDog( Animal parent ){
              super( parent );
              init(parent);
          }
      
          private void init(Animal parent){
              Animal parent = done();
              Farm farm = (parent == null) ? null : parent.done();
              this.human = new Human(farm);
          }
      
          public Human findsHuman(){
              return this.human;
          }
      }
      
      
      class Cat extends CatOrDog{
      
          public Cat(){
              super();
          }
      
          public Cat( Animal parent ){
              super( parent );
          }
      
          public Cat meow(){
              System.out.println("cat says meow");
              return this;
          }
      }
      
      
      class Dog extends CatOrDog {
      
          public Dog(){
              super();
          }
      
          public Dog( Animal parent ){
              super( parent );
          }
      
          public Dog bark(){
              System.out.println("dog says woof");
              return this;
          }
      
          public Dog chacesCar(){
              System.out.println("cat drinks milk");
              return this;
          }
      }
      
      Farm farm = new Farm();
      farm.animal()
          .cat()
              .meow()
              .findsHuman()
                  .saysHello()
                  .done()
              .animal()
          .dog()
              .bark()
              .chacesCar()
              .findsHuman()
                  .saysHello()
                  .done()
              .animal()
          .done()
      .human()
          .saysHello()
          .done();
      
      cat says meow
      human says hi
      dog says woof
      cat drinks milk
      human says hi
      human says hi
      
      cat says meow
      human says hi
      dog says woof
      cat drinks milk
      human says hi
      human says hi
      
      abstract class Base<T extends Base<?>> {
      
          private final T parent;
      
          Base() {
              this.parent = null;
          }
      
          Base(T parent) {
              this.parent = parent;
          }
      
          public T done() throws NullPointerException {
              if (parent != null) {
                  return parent;
              }
      
              throw new NullPointerException();
          }
      }
      
      class Farm<T extends Base<?>> extends Base<T> {
      
          private final Animal<Farm<T>> animal;
          private final Human<Farm<T>> human;
      
          public Farm() {
              super();
              this.animal = new Animal<>(this);
              this.human = new Human<>(this);
          }
      
          public Animal<Farm<T>> animal() {
              return this.animal;
          }
      
          public Human<Farm<T>> human() {
              return this.human;
          }
      }
      
      class Animal<T extends Base<?>> extends Base<T> {
      
          private Cat<Animal<T>> cat;
          private Dog<Animal<T>> dog;
      
          public Animal() {
              super();
              init();
          }
      
          public Animal(T parent) {
              super(parent);
              init();
          }
      
          private void init() {
              this.cat = new Cat<>(this);
              this.dog = new Dog<>(this);
          }
      
          public Cat<Animal<T>> cat() {
              return cat;
          }
      
          public Dog<Animal<T>> dog() {
              return dog;
          }
      }
      
      class Human<T extends Base<?>> extends Base<T> {
          public Human() {
              super();
          }
      
          public Human(T parent) {
              super(parent);
          }
      
          public Human<T> saysHello() {
              System.out.println("human says hi");
              return this;
          }
      }
      
      class Cat<T extends Base<?>> extends Base<T> {
      
          private Human<Cat<T>> human;
      
          public Cat() {
              super();
              init();
          }
      
          public Cat(T parent) {
              super(parent);
              init();
          }
      
          private void init() {
              this.human = new Human<>(this);
          }
      
          public Cat<T> meow() {
              System.out.println("cat says meow");
              return this;
          }
      
          public Human<Cat<T>> findsHuman() {
              return this.human;
          }
      }
      
      class Dog<T extends Base<?>> extends Base<T> {
      
          private Human<Dog<T>> human;
      
          public Dog() {
              super();
              init();
          }
      
          public Dog(T parent) {
              super(parent);
              init();
          }
      
          private void init() {
              this.human = new Human<>(this);
          }
      
          public Dog<T> bark() {
              System.out.println("dog says woof");
              return this;
          }
      
          public Dog<T> chacesCar() {
              System.out.println("cat drinks milk");
              return this;
          }
      
          public Human<Dog<T>> findsHuman() {
              return this.human;
          }
      
      }
      
      public static void main(String[] args) {
          Farm<?> farm = new Farm<>();
          farm
              .animal()
                  .cat()
                      .meow()
                      .findsHuman()
                          .saysHello()
                          .done()
                      .done()
                  .dog()
                      .bark()
                      .chacesCar()
                      .findsHuman()
                          .saysHello()
                          .done()
                      .done()
                  .done()
              .human()
                  .saysHello()
                  .done();
      
          Human human = new Human()
                  .saysHello();
      }