【问题标题】:Super-class reference variable to a sub-class object accesses the subclass's attribute instead of the super's子类对象的超类引用变量访问子类的属性而不是超类的属性
【发布时间】:2020-03-10 15:16:22
【问题描述】:

在我的代码中,我有 3 个类: 班级A

public class A {
    int x = 1;
    static double y = 3.0;
    public A() {
    x = (int)y;
    }
    public A(int x) {
    this .x = this . getX () + x;
    }
    int getX () {
    return this .x;
    }
    public void f( float z) {
    y *= z;
    }
}

B,扩展A

public class B extends A {
    int x = 7;
    public B(int x) {
    super (x);
    this .x = x;
    }
    public B() {
    this .y += 1.0;
    }
    int getX () {
    return this .x;
    }
    public void f( long z) {
    y += z;
    }
    public void f( double z) {
    y -= z;
    }
}

和类M,其中包括main函数

public class M {
    public static void main ( String [] args ) {
        A a1 = new A();
        System .out. println (a1.x + " " + A.y); // OUT: [ ] [ ]
        B b1 = new B();
        System .out. println (b1.x + " " + A.y); // OUT: [ ] [ ]
        System .out. println ((( A)b1 ).x); // OUT: [ ]
        A ab = new B (5);
        System .out. println (ab.x + " " + A.y); // OUT: [ ] [ ]
        System .out. println ((( A)ab ).x); // OUT: [ ]
        A.y = 5.0;
        b1.f (2.0f);
        System .out. println (A.y); // OUT: [ ]
        ab.f (5);
        System .out. println (A.y); // OUT: [ ]
        }
}

main 方法中的每个调用函数都按预期运行,但以下两个除外:

        A ab = new B (5);
        System .out. println (ab.x + " " + A.y); // OUT: [ ] [ ]
        System .out. println ((( A)ab ).x); // OUT: [ ]

这给了

5 4.0
5

作为输出,而我希望它给出

6 4.0
6

现在,据我了解,在创建 B 类型的新对象时,该对象由 A 类型的引用变量 ab 引用,在调用正确的构造函数后,变量 x超类中的值应为6,而子类中的另一个x 等于5

如果这是对的,那么,ab.x 不应该引用超类中的x,它等于6,因为处理了属性和静态方法(与非静态方法相反)在编译时,这意味着println 方法应该在与引用变量类型相同的类中打印变量?

如果是(( A)ab ).x),在B 类中的x 不应该在投射ab 后不可见吗?

如果您能指导我了解为什么会发生这种情况,我将不胜感激。

【问题讨论】:

  • A 构造函数中的this .x = this . getX () + x; 使用了B 中的重写函数getX,这就是原因

标签: java oop polymorphism


【解决方案1】:

这条语句this.x = this.getX() + x; in A constructor将调用getX from B,因此超类中的变量x的值将是5而不是6

所以当你调用这个语句时

A ab = new B (5);

流量会

它会在class B调用参数化构造函数,然后会遇到super(x)语句,所以它会在class A调用参数化构造函数,你有这个语句this.x = this.getX() + x;会调用class BgetX()这将返回this.x(这里x值作为0返回)所以this.x = this.getX() + x;的最终值为(0+5 = 5),this.x的最终值为5。 class Aclass B 变量 x 的值将是 5。

这就是为什么您的以下语句返回的原因

System .out. println (ab.x + " " + A.y); // OUT: [5] [3.0]
System .out. println ((( A)ab ).x); // OUT: [5]

【讨论】:

  • 非常感谢。我想我明白了。只有一件事,我还不明白;为什么this.getX() 会返回0class B 中的 x 不等于 7 吗?
  • 或者它有一个默认值0,因为它是一个实例变量并且构造函数块还没有完全执行?在这种情况下,这是否意味着首先创建实例变量,给定默认值,然后执行正确的构造函数块,然后将声明的值分配给变量,即使该值不在构造函数块内?
  • @Mohamed Fathy,是的,你是对的,this.getX(),这里 this 将引用 B 类的对象,B 实例的值 x 为 0,因为到目前为止还没有值被分配到B类的x
猜你喜欢
  • 2021-03-13
  • 2013-03-24
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多