Method chain: how to use getThis () trick in case of multi-level inheritance

My question in the context of Method Chain + Inheritance doesn't fit well? . But, unfortunately, all the examples / answers of the method chain use the same level of inheritance. My account includes multi-level inheritance like

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

To create a Dog object, I will use either DogBuilder or DogType1Builder

how to use getThis trick for the above use case?

I want to use a template to build a complex Dog object (Dog Object Model) . DogType1 will have some additional properties.

so to use the getThis Trick declaration above the classes would look 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

Method 1.builder 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 parameterized, so to create an instance of "DogBuilder" I have to use

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

Is there a better way?

+6
source share
2 answers

The root of your problem is the class design problem: which you are trying to inherit from a particular class , which is almost always a mistake, and (your example) will inevitably lead to numerous problems. To adhere to the example given in the mentioned thread, you should not create Dog instances, since in such a universe there can be no Dog , no more than Pet - only Poodle s, NewFoundland s, Spaniel , etc. Therefore, getThis should not be implemented on middle (abstract) classes, only in (specific) sheet classes. And in all abstract mid-level classes, you should refer only to a parameter of type type T instead of the actual class name.

Here is an example in response to the mentioned stream , rewritten in accordance with 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(); } } 
+8
source

I do not believe that you can use the getThis trick for several levels of inheritance. You have a superclass, Pet<T extends Pet<T>> , the first subclass, Dog extends Pet<Dog> and the second subclass Poodle extends Dog . With the getThis trick, you have a protected T getThis() method and methods like public T rollOver() . This means that both Poodle and Dog have protected Dog getThis() methods protected Dog getThis() and public Dog rollOver() .

I would suggest Michael Myers suggest using covariant return types.

+1
source

Source: https://habr.com/ru/post/910441/


All Articles