首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果我已经完成了向上转换,为什么要重写从子类调用的方法?

如果我已经完成了向上转换,为什么要重写从子类调用的方法?
EN

Stack Overflow用户
提问于 2017-08-13 12:50:58
回答 3查看 2.5K关注 0票数 5

我刚刚开始学习java::Inheritance和困惑,同时混合转换。

代码语言:javascript
复制
class Example{
     public void methodOne(){
        System.out.println("Example::Method_1");
     }

     public void methodTwo(){
        System.out.println("Example::Method_2");
     }
}

public class Test extends Example{

     public void methodTwo(){                  //Method overriding
        System.out.println("Test::Method_2");
     }

     public void methodThree(){
        System.out.println("Test::Method_3");
     }

    public static void main(String[] args){

        Example exa = new Test();             // UpCasting

        exa.methodOne();                      // Printing Example::Method_1
        exa.methodTwo();                      // Printing Test::Method_2
        // exa.methodThree();                 // Error : can not find symbol
 }
}

有谁能解释一下,这里发生了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-13 12:52:49

在使用继承时,对调用方法的对象的引用的编译时类型仅用于查看(在编译时)是否可以调用该方法。

但是在调用时,编译时类型是什么并不重要。在这种情况下,真正重要的是对象的运行时类型。它是Test,所以首先在Test上搜索该方法。

对于methodOne()来说,这有点不同:它没有被Test覆盖,因此调用来自其超类(Example)的版本。

票数 10
EN

Stack Overflow用户

发布于 2017-08-13 12:59:47

Test扩展Example并重写methodTwo的实现,同时添加新的方法methodThree。现在在你的主

代码语言:javascript
复制
public static void main(String[] args){

        Example exa = new Test();             // UpCasting

        exa.methodOne();                      // Printing Example::Method_1
        exa.methodTwo();                      // Printing Test::Method_2
        // exa.methodThree();                 // Error : can not find symbol
 }

变量exa的静态类型是Example,因此Example类中定义的公共方法限制了exa.methodThree()的使用,因此调用exa.methodThree()(未定义为Example)是非法的。

对于在Example类中定义的方法,在运行时存在动态绑定,这将导致基于exa变量所指向的引用的具体实现。因此,exa.methodTwo()调用将导致被覆盖函数的执行,因为动态类型是Test。而且,由于Test不覆盖methodOne调用,所以exa.methodOne()将导致Example定义的实现。

票数 2
EN

Stack Overflow用户

发布于 2017-08-13 15:27:27

如果我们创建子类的对象并使用超类的引用,那么运行时时间动态绑定就意味着在运行时就会决定应该调用哪个对象。在您的示例中: 1. exa.methodOne(); methodOne属于超类,它在子类中不被重写,因此将执行父类方法。在这里,如果创建像Test test = new Test();这样的对象,那么test.methodOne()也会给出相同的结果。

  1. 这里的exa.methodTwo();在子类中被重写,所以在运行时,重写的方法将被绑定,而同样的方法将被执行。
  2. 在第三种情况下,它给出了错误,因为您使用的是父类引用,但是methodThree()不是父类的一部分,因此会抛出编译错误。如果想调用第三种方法,那么您可以这样调用:Test test = new Test(); test.methodThree()

FYI

为了安全起见,如果我们想要覆盖任何父类方法,那么我们应该始终在子调用方法中使用@重写注释。它将有助于避免任何方法覆盖故障。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45660541

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档