I'm facing the problem described in this question but would like to find a solution (if possible) without all the casts and @SuppressWarning annotations.
A better solution would be one that builds upon the referenced one by:
Solutions presented here will be graded with 2 points based on the criteria. Bounty goes to solution with most points or the "most elegant" one if there is more than one with 2 points.
No cast, no @SuppressWarning, few lines only:
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;
}
}
One approach is to define an abstract method getThis()
in Parent
class, and make all the Child
classes override it, returning the this
reference. This is a way to recover the type of this
object in a class hierarchy.
The code would 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 per requirement, there is no Casting and no @SuppressWarnings . I learnt this trick few days back from Angelika Langer - Java Generics FAQs .
Reference:
One solution is to override the method in the child class and change the return type to a more specific one, ie. the child type. This requires casting. Instead of using the typical (Child)
cast, 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;
}
}
The cast is hidden within the standard method. From the source of Class
.
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.