方法链接:如何在多级继承的情况下使用getThis()技巧 [英] Method Chaining: How to use getThis() trick in case of multi level inheritance

查看:110
本文介绍了方法链接:如何在多级继承的情况下使用getThis()技巧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是在方法链接+继承的背景下一起玩?
但不幸的是,方法链接的所有示例/答案都使用单一级别的继承。
我的用例涉及到多层次的继承,例如:
$ b $ pre $ 抽象类PetBuilder {...}
class DogBuilder扩展了PetBuilder {..}
类DogType1Builder扩展了DogBuilder {...}

构建一个Dog对象,我将使用DogBuilder或DogType1Builder



如何使用getThis技巧获取上述用例?

我想使用构建器模式来构建一个复杂的Dog对象(Dog Object Model)
DogType1将添加一些属性。



所以使用getThis Trick宣布上面的类将变成类似于

 抽象类PetBuilder< T extends PetBuilder< T>> 
类DogBuilder< T扩展DogBuilder>扩展PetBuilder< DogBuilder>>
类DogType1Builder扩展了DogBuilder< DogType1Builder>
< / code>



现在,这会产生两个问题:

在'DogBuilder'中的1.builder方法看起来像

  public T someMethodInDog(String dogName){
..
return(T)this; ///我不想使用类型转换,但我不能使用getThis Trick Here(编译器报告从DogBuilder转换为T的错误)
}

2.由于DogBuilder已经参数化,因此要创建DogBuilder实例,我将不得不使用

  DogBuilder< DogBuilder> builder = new DogBuilder(); //传递< DogBuilder>类型...真正的痛苦

有更好的方法吗?

解决方案

您的问题的根源在于类设计问题:您试图从具体类继承

这几乎总是一个错误,并且(你的例子)必然会导致很多问题。要坚持引用线程中给出的示例,您不应该实例化 Dog ,因为在这样的Universe中可以不存在 Dog s,超过 Pet s - 只有 Poodle s, NewFoundland s, Spaniel s等。因此, getThis 不应该在mid-级别(抽象)类,只能在(具体)叶子类中使用。在所有中级抽象类中,只能引用泛型类型参数 T ,而不是实际的类名。



以下是根据上述规则重写的对引用线索的回答中的示例:

  public class TestClass {

静态抽象类Pet< T extends Pet< T>> {
私人字符串名称;

protected abstract T getThis();

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

静态类Cat延伸Pet< Cat> {
@Override受保护的猫getThis(){return this; }
$ b $ public Cat catchMice(){
System.out.println(我抓到一个鼠标!);
return getThis();
}
}

//狗是抽象的 - 只有具体的狗品种可以实例化
静态抽象类Dog< T extends Dog< T>>延伸Pet T> {
// getThis在这里没有实现 - 只在具体的子类中

//返回具体的狗品种,而不是一般狗
public T catchFrisbee(){
System.out.println(我抓到了一个飞盘!);
return getThis();
}
}

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

public Poodle sleep(){
System.out.println(我正在睡觉!);
return getThis();
}
}

静态类NewFoundland扩展Dog< NewFoundland> {
@Override受保护的NewFoundland getThis(){return this; }

NewFoundland swim(){
System.out.println(我游泳!);
return getThis();



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


My question is in context of Method chaining + inheritance don’t play well together?. But unfortunately all examples/answers of method chaining uses single level of inheritance. My usecase involves multi level of inheritance for e.g

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

To construct a Dog Object,i will be using either DogBuilder or DogType1Builder

how to use getThis trick for the above use case?

I want to use builder pattern for constructing a complicated Dog object(Dog Object Model)". DogType1 will have some added properties.

so to use getThis Trick declaration of above classes will become like

abstract class PetBuilder<T extends PetBuilder<T>>
class DogBuilder<T extends DogBuilder<T>> extends PetBuilder<DogBuilder<T>>
class DogType1Builder extends DogBuilder<DogType1Builder>

Now this creates two problems

1.builder method in 'DogBuilder' will look like

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.As DogBuilder has become parameterised,so to create instance of "DogBuilder" i will have to use

DogBuilder<DogBuilder> builder=new DogBuilder(); //passing <DogBuilder> type ...real pain

Is there a better way?

解决方案

The root of your problem is a class design issue: you are trying to inherit from a concrete class, which is almost always a mistake, and (your case in point) is bound to cause numerous problems. To stick with the example given in the referred thread, you should not be instantiating Dog, as in such a universe there can exist no Dogs in general, any more than Pets - only Poodles, NewFoundlands, Spaniels etc. Consequently, getThis should not be implemented in mid-level (abstract) classes, only in the (concrete) leaf classes. And in all mid-level abstract classes, you should only refer to the generic type parameter T, instead of the actual class name.

Here is the example in the answer to the referred thread rewritten according to the above rules:

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();
  }
}

这篇关于方法链接:如何在多级继承的情况下使用getThis()技巧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆