【问题标题】:Can somebody please explain me this output of polymorphism?有人可以解释一下这种多态性的输出吗?
【发布时间】:2013-08-23 17:18:53
【问题描述】:

代码如下:

class A{
    int data=10;
    void show1(){
        System.out.println("In A="+data);
    }
}

class B extends A{
    int data=20;
    void show2(){
        System.out.println("In B="+data);
    }



}


public class Overriding4 {
    public static void main(String args[]){
        B b=new B();
        System.out.println("Data1="+b.data);
        System.out.println("Data2="+b.data);
        b.show1();
        b.show2();
    }
}

这是输出:

Data1=20
Data2=20
In A=10
In B=20

Data1=20 的输出应该是 10 ,而不是 20 ......但我想我在这里遗漏了一些东西。请帮我解决这个问题

好的,感谢您的帮助,但有一个新疑问: 如果我将 main 方法更改为:

 public static void main(String args[]){
            A a=new B();
            System.out.println("Data1="+a.data);
            System.out.println("Data2="+a.data);
            a.show1();
            a.show2();
        }

你去。

【问题讨论】:

  • 为什么你认为应该是10
  • 为什么Data1 必须是 10?
  • 它是 20,因为您正在重新声明该字段,因此它使用已声明字段的值,而不是超类中的字段值。您实际上应该尝试避免重复的字段名称(存在于超类和子类中的字段名称),因为它可能会避免很多混乱。
  • 您重载了数据变量。如果您想要与方法名称不同的东西,请重命名它。如果您在扩展类中具有相同的方法/变量名称,它们就会重载。
  • 您为什么认为b.data 是第一个println 的一个值,而下一个println 是一个不同的值?

标签: java polymorphism ocpjp


【解决方案1】:

类字段不会被继承。请注意,AB 两个类中都有相同的 int data 字段。这称为Hiding

【讨论】:

    【解决方案2】:

    为了“感受”多态性的力量,我们需要稍微修改一下代码:

    class A {
    
        int data=10;
        void show(){
            System.out.println("In A="+data);
        }
    }
    
    class B extends A {
    
        int data=20;
    
        @Override
        void show(){
            System.out.println("In B="+data);
        }
    
        public static void main(String args[]){
            A a = new A();
            A b = new B();
            a.show();
            b.show();
        }
    }
    

    现在,您可以看到ab 都被声明为A 类型——但是赋值才是真正的区别。此外,我们可以创建一个类型 A 的数组,并使用两种类型的对象(AB)来容纳它:

    A[] arr = new A[3];
    

    // 让我们添加一些东西;

    arr[0] = new A(); 
    arr[1] = new B();
    arr[2] = new A();
    

    现在很容易看出美丽的多态是如何工作的L

    for (int i=0; i<arr.length; i++){
       arr[i].show();
    }
    

    最后一个循环将打印:

    In A 10
    In B 20
    In A 10
    

    我们所知道的是,数组包含的对象是A 的子类型——我们可以指望每个对象调用“正确的”show() 方法。这就是多态性!

    【讨论】:

      【解决方案3】:
      Within a class, a field that has the same name as a field in the superclass hides
      the superclass's field, even if their types are different. 
      

      这可以在Hiding fields找到

      因此,它打印 20。

      【讨论】:

        【解决方案4】:

        由于您已经覆盖了 B 类中的数据变量,它将打印最新的值。由于您在 B 类中将“数据”重估为 20,这就是它将显示的内容。

        【讨论】:

          【解决方案5】:

          除非你打错字,否则下面两行基本相同:

          System.out.println("Data1="+b.data);
          System.out.println("Data2="+b.data);
          

          像这样可视化对象可能会有所帮助:

          A {
            [A.data = 10];  <-- this is overridden and cannot be accessed directly
            show1() => 10;
            B {
              B.data => 20;
              show2() => 20;
            }
          }
          

          【讨论】:

            【解决方案6】:

            B 类的对象有两个字段,都名为 data,但正如 Luiggi 所暗示的,其中一个是隐藏的。如果您想找回它,请使用演员表:

            public class Overriding4 {
                public static void main(String args[]){
                    B b=new B();
                    System.out.println("Data1="+((A)b).data);  // like this  
                    System.out.println("Data2="+b.data);
                    b.show1();
                    b.show2();
                }
            }
            

            产生:

            Data1=10
            Data2=20
            In A=10
            In B=20
            

            附:您可以在作业的任一侧使用演员表:

            public class Overriding4 {
                public static void main(String args[]){
                    B b=new B();
                    ((A)b).data *= 10;
                    System.out.println("Data1="+((A)b).data);  
                    System.out.println("Data2="+b.data);
                    b.show1();
                    b.show2();
                }
            }
            
            Data1=100
            Data2=20
            In A=100
            In B=20
            

            PPS。我发布这篇文章是为了向您展示该语言的工作原理,但总的来说,在类中拥有其他类可以直接读写的公共字段不是一个好主意。见Why use getters and setters?

            【讨论】:

              【解决方案7】:

              您实际上并没有覆盖方法....

              `System.out.println("Data1="+b.data);

              System.out.println("Data2="+b.data);`

              对于这两行,“数据”值将从 B 类的数据变量中获取。 现在,B 类扩展了 A 类,这意味着 A 类的所有成员都将在 B 类中继承。所以变量 i(A 类的)将被继承,在 B 类内部我们有自己的局部变量 i..... A 类的 .show1() 方法也将在 B 类中继承。 因此,通过使用 B 类的引用变量(b),我们可以访问 show1() 方法以及 show2() 方法。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-07-29
                • 1970-01-01
                • 2018-07-29
                • 1970-01-01
                • 1970-01-01
                • 2020-12-18
                • 2018-07-28
                • 1970-01-01
                相关资源
                最近更新 更多