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

时间:2017-08-13 12:50:58

标签: java inheritance polymorphism upcasting

我刚刚开始学习java :: Inheritance并混淆了Up-Casting。

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
 }
}
可能有人请解释一下,这里发生了什么?

3 个答案:

答案 0 :(得分:9)

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

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

对于Test,它有点不同:它不会被Example覆盖,因此会调用其超类(model.firstChord.fifth)中的版本。

答案 1 :(得分:2)

Test扩展Example并在添加新方法methodTwo时覆盖methodThree的实现。现在在你的主要

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,因此API使用受Example类中定义的公共方法的限制,因此调用exa.methodThree()是非法的(不是定义它Example)。

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

答案 2 :(得分:1)

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

  1. exa.methodTwo();这里的methodTwo在子类中被重写,因此在运行时覆盖的方法将被绑定并且将被执行。

  2. 在第三种情况下,它给出错误,因为您正在使用父类引用但methodThree()不是父类的一部分,因此抛出了编译错误。 如果想打电话给第三种方法,那么你可以这样打电话:Test test = new Test(); test.methodThree()

  3. FYI,

    为了安全起见,如果我们想覆盖任何父类方法,我们应该总是在子调用方法中使用@Override注释。它将有助于避免任何方法覆盖毛刺。