[英]Avoid casting in inherited java-classes
我有一堂课:
class MyClass {
public MyClass getParent() { ... }
public MyClass[] getChildren() { ... }
....
}
和一个子类
MySubClass extends MyClass {
public String getId() { }
...
}
每次我在MySubClass
的实例上使用getChildren()
或getParent()
时,都必须转换MySubClass
方法的结果,例如:
MySubClass sub = new MySubClass();
((MySubClass)sub.getParent()).getId();
有什么方法(通过语言或设计)来避免这种转换?
感谢您的任何想法!
更新我想要的是getParent()
和getChildren()
始终返回从中调用它们的实例的类型,例如sub.getChildren()
应该返回MySubClass[]
您可以使用自我类型模式:
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
引用的字段,并知道它们至少起MyClass
引用的作用,等等。 而且,如果您在MySubClass
上调用getParent
或getChildren
,则可以将返回值用作MySubClass
实例,并且不进行任何强制转换。
这种方法的主要缺点是,以前从未看过的人会变得很困惑。
有什么方法(通过语言或设计)来避免这种转换?
答案是否定的 。 如果要访问超类字段或方法,则必须显式强制转换。
从Java 5.0开始,您可以重写具有协变返回类型的方法,即,您可以重写方法以返回子类的父类。 (请参阅Java中的Covariant返回类型 ):
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实例作为父项和/或子项的情况下才有效
是的,假设您知道MySubClass
的父级和子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() { }
...
}
也许使用泛型( 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 "";
}
}
根据您实际要执行的操作,使您的基类成为抽象并添加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() {
...
}
也将方法getId添加到超类,即。 我的课。
任何子类仍然可以重写并具有自己的实现。 如果您担心子类不会覆盖getId,则从getId的超类中引发异常。
有趣的是,getID是适用于所有类的东西,因此可以添加到super中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.