我有一个班级:
class MyClass {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
....
}
和子类
MySubClass extends MyClass {
public String getId() { }
...
}
每次我在getChildren()
的实例上使用getParent()
或MySubClass
时,我都必须投出theese方法的结果,例如:
MySubClass sub = new MySubClass();
((MySubClass)sub.getParent()).getId();
有没有办法(通过语言或设计)避免这种演员?
感谢您的任何想法!
更新
我想要的是getParent()
和getChildren()
总是返回它们被调用的实例的类型,例如sub.getChildren()
应该返回MySubClass[]
答案 0 :(得分:10)
您可以使用自我类型模式:
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() { ... }
}
您可以根据需要实施getParent
和getChildren
方法,声明MyClass
中包含T
引用的字段,并知道它们的行为至少为{{1}引用,等等。如果您在MyClass
上致电getParent
或getChildren
,则可以将返回值用作MySubClass
个实例,而无需在任何地方投射。
这种方法的主要缺点是之前没有见过它的人往往会感到非常困惑。
答案 1 :(得分:4)
有没有办法(通过语言或设计)来避免这种演员?
答案是否。如果要访问超类字段或方法,则必须显式转换。
答案 2 :(得分:3)
从Java 5.0开始,您可以使用协变返回类型覆盖方法,即您可以覆盖方法以返回子类父类。 (见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() {
...
}
}
然后,您可以拨打new MySubClass().getChildren()[0].getId()
。
当然,只有MySubClass
始终将MySubClass实例作为父级和/或子级
答案 3 :(得分:1)
是的,假设您知道MySubClass
的父级和子级将始终属于MySubClass
类型。
在这种情况下,您可以缩小MySubClass
中的返回类型并在那里进行转换:
MySubClass extends MyClass() {
@Overrides
public MySubClass getParent() { return (MySubclass) super.getParent(); }
@Overrides
public MySubClass[] getChildren() { return (MySubclass[]) super.getChildren(); }
public String getId() { }
...
}
答案 4 :(得分:1)
也许使用泛型(http://docs.oracle.com/javase/tutorial/extra/generics/index.html)
你应该有这样的东西:
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 "";
}
}
答案 5 :(得分:0)
根据您实际要做的事情,将您的基类抽象化并添加getId():
abstract class MyClass() {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
public String getId();
....
}
MySubClass extends MyClass() {
@Overrides
public String getId() { }
...
}
或者,根据您的要求,在基类中实现getId():
class MyClass() {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
public String getId() { }
....
}
MySubClass extends MyClass() {
...
}
答案 6 :(得分:0)
将方法getId添加到超类中,即。我的课。
任何子类仍然可以覆盖并拥有自己的实现。 如果你害怕子类没有重写getId,那么从getId中抛出超类的异常。
从理论上讲,getID是适用于All Class的东西,因此可以添加到super。