【问题标题】:Dynamic polymorphism during overriding覆盖期间的动态多态性
【发布时间】:2013-02-16 13:34:23
【问题描述】:

我在 A 类中创建了两个方法,在 B 类中被覆盖,如下所示。我有一些与动态多态性和覆盖有关的问题。

这是我的 B 类扩展 A 类的代码。

public class A {


    public void methoda()
    {
        System.out.println("a");
    }
    public void methodb()
    {
        System.out.println("aaa");
    }
    public static void main(String[] args) {
    B a =new B();
    A b=a;
    b.methoda();


    }

}

public class B extends A{
@overrides
public void methoda()
{
    System.out.println("A");
}
@overrides
public void methodb()
{
    System.out.println("g");
}
}

这里我重写了两个方法,当使用超类引用时,调用的方法取决于运行时确定的对象类型,是动态多态性的一个示例。

但是,如果我对子类对象使用子类引用并覆盖该方法,那么被覆盖的将在运行时得到解决,并且是动态多态的情况,或者仅在编译时解决,因为对象类型和引用是相同的类型和不保留动态多态的情况吗?

重写和动态多态是否总是同时发生??

【问题讨论】:

    标签: java reference polymorphism overriding


    【解决方案1】:

    我不确定我是否理解这个问题,但多态方法总是在运行时解决。执行的方法是对象的具体运行时类型之一。引用它的变量的声明类型无关紧要。

    狮子就是狮子,它总是会咆哮,即使你把它称为动物。

    【讨论】:

    • 多态方法意味着在运行时解决的覆盖方法??
    • @AnubhavNigam:是的 - 这是 Java 编程的巨大优势之一。
    • 是的。多态方法是可以被覆盖的方法,即非最终的、非私有的方法。
    • @JB Nizet 像多态性意味着一个对象可以有多种形式,例如,狮子也可以有其种类和动物的形式,但是当我只对它的对象使用狮子的引用时它仍然是动态多态的情况吗??
    • @Andrew Martin 是的,我知道只有在使用 new 关键字并且在运行时创建对象时才实例化一个类,正如 Jbnet 在上一个答案中所说的那样,当方法被覆盖时,多态性根本不依赖于引用变量.
    【解决方案2】:

    首先,(subtype) polymorphism 始终是动态的(即在运行时),因此“动态”修饰符是多余的,除非它用于区分 ad-hoc polymorphismparametric polymorphism

    其次,@Override(not @overrides) 注释不是强制性的(实际上它只是由 Java 5.0 引入),尽管它被推荐为更具可读性(明确显示被覆盖的方法)等等健壮(编译器将检查拼写错误的方法)代码。

    总之,方法覆盖是OOP语言的关键特性,注解@Override在编译时被检查,而多态行为在运行时被解析。

    【讨论】:

    • 是的,我没有(@override)在 Eclipse 编辑器中添加它,我在这里发布问题时添加了它
    • @Hui。当我在您的答案中阅读“动态”修饰符时,我感到困惑。没有名为“动态”的修饰符。但是,当我第二次阅读您的答案时,我明白您想说什么。更清楚一点:多态性具有内在的含义,即它是动态的,即在运行时。因此,当您说多态时,它隐含地表示动态/运行时。
    【解决方案3】:

    是否被子类引用都没有关系。重要的是创建的实例。如果你的实例是从 B 创建的,你会得到 B 的结果。

    【讨论】:

    • 是的,我知道,因为对象类型是 b,但是当引用和对象类型都属于同一类型并且我正在覆盖超类的方法时
    • for ex A a=new B(); a.methoda();这里编译时类型是a类,其中运行时类型是b类,所以调用的方法属于b类,是动态多态性的一个例子,但现在如果我做B b=new B();这里的编译时间和运行时间都是相同的所以现在仍然是被覆盖的方法是动态多态性并且被覆盖的方法总是在@运行时解析
    【解决方案4】:

    如果您使用对子类对象的子类引用,则无需覆盖。仅当基类的指针指向其子类之一的对象并且此指针调用基类的方法时,才会发生覆盖。 . 但实际执行的方法是子类的方法。

    【讨论】:

      【解决方案5】:
      class Bike {  
         void run() {
            System.out.println("running");
         }  
      }  
      
      class Splender extends Bike {  
         void run() {
            System.out.println("Bike is running");
         }  
      
         public static void main(String args[]) {
      
            Bike a = new Bike();
            a.run(); //output: running
      
            Bike b = new Splender();  
            b.run(); //output: Bike is running 
         }  
      } 
      

      这里的超类(自行车)引用指向子类对象。该对象是在运行时而不是在编译时创建的。没关系,

      1) 引用变量和对象类型相同或

      2) 引用变量是超类类型,对象是子类类型。

      在上述示例中,编译器无法确定对象类型,因为 Splender 的实例也是 Bike 的实例。 JVM 在运行时根据创建的对象类型调用该方法。这两种情况都是动态多态性而不是编译时多态性。

      【讨论】:

        猜你喜欢
        • 2012-02-08
        • 2011-06-26
        • 2012-10-11
        • 2011-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-02
        • 2010-09-14
        相关资源
        最近更新 更多