繁体   English   中英

避免在继承的Java类中进行强制转换

[英]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() { ... }
}

您可以根据需要实现getParentgetChildren方法,在MyClass中声明包含T引用的字段,并知道它们至少起MyClass引用的作用,等等。 而且,如果您在MySubClass上调用getParentgetChildren ,则可以将返回值用作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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM