Most probably, inside the abstract class there something like this:
public abstract class SomeClass<T extends SomeClass<T>> implements Cloneable {
public abstract T someMethod(); //<-- variable return type should be the implementing class itself
public abstract int someOtherMethod(T someInstance); //<-- variable parameter type should be the implementing class itself
}
With such declaration, when you extend the class SomeClass
with something concrete, let's say SomeConcreteClass
, then you'll have:
public class SomeConcreteClass extends SomeClass<SomeConcreteClass> {
@Override
public SomeConcreteClass someMethod() {
//implementation that returns SomeConcreteClass
}
@Override
public int someOtherMethod(SomeConcreteClass instance) {
//implementation that takes in parameter this type of class
}
}
When you declare an abstract class like that, you basically ask to self-reference the child class in the parameter type.
Of course you may also use another child (it would still be inside bounds as long as it extends SomeClass
), but it's a rare use case (I'll never seen it personally)