Inherited method returns reference type

I ran into the problem described in this question , but would like to find a solution (if possible) without all the throws and @SuppressWarning annotations.

A better solution would be one that is based on a reference:

  • @SuppressWarning removal
  • drop dropping

The solutions presented here will be rated at 2 points based on criteria. Bounty moves on to the decision with the most points or the “most elegant” if there is more than one with 2 points.

+8
java generics inheritance
source share
3 answers

No throws, no @SuppressWarning, just a few lines:

public abstract class SuperClass<T extends SuperClass<T>> { protected T that; public T chain() { return that; } } public class SubClass1 extends SuperClass<SubClass1> { public SubClass1() { that = this; } } public class SubClass2 extends SuperClass<SubClass2> { public SubClass2() { that = this; } } 
+9
source share

One approach is to define the abstract getThis() method in the Parent class and make all Child classes override it by returning the this link. This is a way to restore the type of the this object in the class hierarchy.

The code will look like this:

 abstract class Parent<T extends Parent<T>> { protected abstract T getThis(); public T example() { System.out.println(this.getClass().getCanonicalName()); return getThis(); } } class ChildA extends Parent<ChildA> { @Override protected ChildA getThis() { return this; } public ChildA childAMethod() { System.out.println(this.getClass().getCanonicalName()); return this; } } class ChildB extends Parent<ChildB> { @Override protected ChildB getThis() { return this; } public ChildB childBMethod() { return this; } } public class Main { public static void main(String[] args) throws NoSuchMethodException { ChildA childA = new ChildA(); ChildB childB = new ChildB(); childA.example().childAMethod().example(); childB.example().childBMethod().example(); } } 

As required, no Casting and no @SuppressWarnings. I learned this trick a few days ago from Angelika Langer - Java Generics FAQ .

Reference:

+5
source share

One solution is to override the method in the child class and change the return type to a more specific one, i.e. type of child. This requires casting. Instead of using a typical cast (Child) use the Class#cast(Object) method

 public class Parent { public Parent example() { System.out.println(this.getClass().getCanonicalName()); return this; } } public class Child extends Parent { public Child example() { return Child.class.cast(super.example()); } public Child method() { return this; } } 

Casting is hidden in the standard method. From source Class .

 public T cast(Object obj) { if (obj != null && !isInstance(obj)) throw new ClassCastException(cannotCastMsg(obj)); return (T) obj; } 
+1
source share

All Articles