I have a class:
class MyClass {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
....
}
and a subclass
Beginning with Java 5.0, you can override methods with covariant return types, i.e. you can override a method to return a subclass parent class. (see Covariant return type in Java):
public class MySubClass extends MyClass {
@Override
public MySubClass getParent() {
return (MySubClass) super.getParent();
}
@Override
public MySubClass[] getChildren() {
return (MySubClass[]) super.getChildren();
}
public String getId() {
...
}
}
You can then call new MySubClass().getChildren()[0].getId()
.
Of course this will only work if MySubClass
always has MySubClass instances as parent and/or children
Maybe using generics (http://docs.oracle.com/javase/tutorial/extra/generics/index.html)
You should have something like this:
public class MyClass<T extends MyClass> {
public T getParent() { return null; }
public MyClass[] getChildren() {
return null;
}
public static void main(String[] args) {
MyClass<MySubClass> o = new MySubClass();
o.getParent().getId();
}
}
class MySubClass extends MyClass<MySubClass> {
public String getId() {
return "";
}
}
Yes, assuming that you know that the parent and children of a MySubClass
will always be of type MySubClass
.
In that case you could just narrow the return types in MySubClass
and do the casting there:
MySubClass extends MyClass() {
@Overrides
public MySubClass getParent() { return (MySubclass) super.getParent(); }
@Overrides
public MySubClass[] getChildren() { return (MySubclass[]) super.getChildren(); }
public String getId() { }
...
}
Depending on what you are actually trying to do, either make your base class abstract and add getId():
abstract class MyClass() {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
public String getId();
....
}
MySubClass extends MyClass() {
@Overrides
public String getId() { }
...
}
Alternatively, depending on your requirements, implement getId() in your base class:
class MyClass() {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
public String getId() { }
....
}
MySubClass extends MyClass() {
...
}
You can use the self-type pattern:
class MyClass<T extends MyClass<T>> {
public T getParent() { ... }
public List<T> getChildren() { ... } // you can use an array here too, but don't :)
}
class MySubclass extends MyClass<MySubclass> {
public String getId() { ... }
}
You can implement your getParent
and getChildren
methods as desired, declare fields in MyClass
that hold T
references and know that they behave at least as MyClass
references, et cetera. And if you call getParent
or getChildren
on a MySubClass
, you can use the return values as MySubClass
instances with no casts anywhere.
The primary disadvantage of this approach is that people who haven't seen it before tend to get pretty confused.
Add the method getId to the super class as well ie. MyClass.
Any subclasses can still override and have their own implementation. If you are scared of subclasses not overriding getId,then throw an exception from the super class from getId.
Th erotically, getID is some thing that is applicable for All Class and hence can be added to super.