方法链接:如何在多级继承的情况下使用getThis()技巧 [英] Method Chaining: How to use getThis() trick in case of multi level inheritance
问题描述
我的问题是在方法链接+继承的背景下一起玩?。
但不幸的是,方法链接的所有示例/答案都使用单一级别的继承。
我的用例涉及到多层次的继承,例如:
$ 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 $一般来说c $ c> 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 Dog
s in general, any more than Pet
s - only Poodle
s, NewFoundland
s, Spaniel
s 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屋!