避免在继承的java类中进行转换

时间:2013-09-30 11:00:36

标签: java inheritance casting

我有一个班级:

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[]

7 个答案:

答案 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() { ... }
}

您可以根据需要实施getParentgetChildren方法,声明MyClass中包含T引用的字段,并知道它们的行为至少为{{1}引用,等等。如果您在MyClass上致电getParentgetChildren,则可以将返回值用作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。