der_Fidelis
der_Fidelis

Reputation: 1515

Returning an instance of the concrete child class from a method in the abstract parent class

I'm wondering if there's a better way to do this. What I want is to have a concrete method in an abstract class return the concrete instance that extends the abstract class.

Here's what I'm doing now:

abstract class ParentClass<T extends ParentClass> extends RelativeLayout {
    ...
    public T aMethod(){
        return (T)this;
    }
}

and

class ChildClass1 extends ParentClass<ChildClass1>{
...
}

I don't think I should have to cast this to T since this always is an instance of T.

Upvotes: 1

Views: 1321

Answers (1)

lexicore
lexicore

Reputation: 43671

The problem is that there is no way to reference the type of "this very class". This is why you have to use constructs like abstract class Base<T extends Base<T>>. But as many mentioned in comments, nothing prohibits you from defining Subclass1 extends <Subclass2>. There is just now syntactic way to guarantee that T is "this very class".

You can, however, enforce this guarantee in the runtime. You can use something like TypeTools or other methods to extract used generic type and the make sure that current instance has this type. This would probably result in something like:

public abstract class Base<T extends Base<T>> {

    protected Base() {
        final Class<?> t = (Class<?>) ((ParameterizedType) getClass().getGenericSuperclass())
                .getActualTypeArguments()[0];
        if (!t.isInstance(this)) {
            throw new IllegalArgumentException();
        }
    }

    public T getInstance() {
        @SuppressWarnings("unchecked")
        T thisIsT = (T) this;
        return thisIsT;
    }
}

This class can be instantiated:

public class Extension1 extends Base<Extension1> {}

But this one not:

public class Extension2 extends Base<Extension1> {}

The Base constructor guarantees that this is instance of T therefore the cast of this to T is safe.

Upvotes: 1

Related Questions