继承中的Java Upcasting或多态性

时间:2019-02-12 22:04:57

标签: java

class Movie {
    public void play() {
        System.out.println("playing movie");
    }

}

class DVD extends Movie {
    @Override
    public void play() {
        System.out.println("playing dvd");
    }

    public void menu() {
        System.out.println("showing menu");
    }

}

public class Main {
    public static void main(String[] args) {
        Movie m = new DVD();
        m.play();
        m.menu(); //error
    }
}

据我了解,m是DVD对象。 因此,它会打印出“正在播放DVD”。 但是为什么

m.menu()

如果未从父类Movie覆盖它,给我一个错误吗? 抱怨我在Movie类中没有menu()方法。

此外,在这种情况下,您将某些对象声明为

Parent obj = new children();

像这样吗? 当您要确保子类中的方法是 被父母取代? 如果是这种情况,为什么不直接在父类中创建方法 “抽象”甚至使父作为接口? 我的标题可能会引起误解,但是这种行为被称为“向上投射”吗?或多态?j

3 个答案:

答案 0 :(得分:3)

当您看到Movie m = new DVD()时,您即人知道m是DVD。但是编译器并不知道-它只知道这是电影,因为这就是您告诉它的一切。因此,当看到m.menu()时,它将在Movie上寻找该方法,但找不到。它不会分析您的代码来确定m实际上是Menu的子类,尤其是DVD的子类,并且该确实具有menu()。它只考虑Movie m,因此抱怨Movie没有方法menu()

在Java中,这种情况一直发生,您可能会遇到类似这样的行:

List<Foo> myList = new ArrayList<>();

请参阅"What does it mean to 'program to an interface'?"关于为什么要这样做的信息。但对于您的问题,请特别注意ArrayList定义了List中未定义的方法trimToSize()。如果您如上所述声明myList,则将无法调用myList.trimToSize()

答案 1 :(得分:1)

我希望这会有所帮助:

就像人们评论的那样,产生错误的原因是因为m被(您)定义为电影。实际上,作为DVD(也是电影)并不矛盾,因此可以正常工作。

将子对象当作父对象存储的原因有很多,例如,如果您希望对属于一个父类的不同子对象(例如DVD,BluRay,盒式磁带等)进行统一处理

您可能还希望Movie本身具有功能,因此将其抽象化对您没有用(想象您正在设计游戏,并且想说Orc和Uruk-Hai,它们是兽人,您仍然希望两者都能独立发挥作用。

最后,不确定这是否是您感兴趣的内容,通过查找“访客模式”,它可能与您最后要问的内容有关。

答案 2 :(得分:1)

  

电影m =新DVD();

由于运行时多态性,

在运行时保留子实例,但是Java是静态/结构类型编程,因此它始终严格维护其类型,因此 Movie 对象始终会找到其结构属性。因此,电影对象 m 在运行时找不到 menu()方法。因此,如果要实现此目标,则必须执行以下操作

  

DVD m =新DVD();

  

对象m =新DVD();

     

(((DVD)m).menu();

  

电影m =新DVD();

     

DVD d =(DVD)m; m.menu();

但是,如果Java是动态类型编程(其中Duck类型用于在运行时解析对象结构),您的想法是正确的。

有关type的更多详细信息,请阅读here