9

我有一堂课:

class MyClass {

  public MyClass getParent() { ... }

  public MyClass[] getChildren() { ... }

  ....

}

和一个子类

MySubClass extends MyClass {

  public String getId() { }

  ...
}

每次我使用getChildren()getParent()的实例时MySubClass,我都必须转换这些方法的结果,例如:

MySubClass sub = new MySubClass();
((MySubClass)sub.getParent()).getId();

有什么办法(通过语言或设计)来避免这种铸造吗?

感谢您的任何想法!

更新 我想要的是getParent()并且getChildren()总是返回它们被调用的实例的类型,例如sub.getChildren()应该返回MySubClass[]

4

7 回答 7

14

您可以使用自类型模式:

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方法,在其中声明包含引用的字段MyClassT知道它们的行为至少与MyClass引用一样,等等。如果您调用getParentor getChildrenMySubClass您可以将返回值用作MySubClass实例,而无需在任何地方进行强制转换。

这种方法的主要缺点是以前没有见过它的人往往会很困惑。

于 2013-09-30T11:17:33.567 回答
4

有什么办法(通过语言或设计)来避免这种铸造吗?

答案是否定的。如果要访问超类字段或方法,则必须显式强制转换。

于 2013-09-30T11:04:36.743 回答
4

从Java 5.0 开始,您可以覆盖具有协变返回类型的方法,即您可以覆盖一个方法以返回一个子类父类。(参见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 实例作为父和/或子实例时才有效

于 2013-09-30T11:13:23.683 回答
1

是的,假设您知道 a 的父级和子级MySubClass将始终是 type MySubClass

在这种情况下,您可以缩小返回类型MySubClass并在那里进行转换:

MySubClass extends MyClass() {
    @Overrides
    public MySubClass getParent() { return (MySubclass) super.getParent(); }

    @Overrides
    public MySubClass[] getChildren() { return (MySubclass[]) super.getChildren(); }

    public String getId() { }

    ...
}
于 2013-09-30T11:12:03.067 回答
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 "";
    }
}
于 2013-09-30T11:13:42.527 回答
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() {
    ...
}
于 2013-09-30T11:06:49.847 回答
0

将方法 getId 也添加到超类中,即。我的课。

任何子类仍然可以覆盖并拥有自己的实现。如果你害怕子类不覆盖 getId,那么从 getId 的超类中抛出异常。

从情色上讲,getID 是适用于所有类的东西,因此可以添加到超级类中。

于 2013-09-30T11:09:04.000 回答