飞镖:实例变量覆盖

时间:2020-06-17 05:07:38

标签: dart

我对类实例变量覆盖的规则感到困惑

class S0 {
  num a;

  S0(this.a) {
    print("in S0 :$a");
  }
}

class S1 extends S0 {
  num a;

  S1(this.a) : super(a + 1) {
    print("in S1 :$a");
  }
}

main() {
  var b = S1(123);
  print(b.a);
}

以上是我的代码。我希望它能打印:

在S0中:124

在S1中:123

123

但是结果是:

在S0中:123

在S1中:123

123

为什么?谢谢!

2 个答案:

答案 0 :(得分:2)

在Dart中,instance variables implicitly create getter and (for non-final members) setter functions。也就是说,S0的接口是隐式的:

class S0 {
  num get a;
  set a(num value);

  S0(num a);
}

从这个角度看,应该更清楚的是,当S0尝试访问a时,它使用其getter方法,在这种情况下,该方法被S1覆盖,因此总是返回{ {1}}的值。

施工顺序也很重要。构造派生的S1类的实例将执行:

  1. 派生类(S1)的初始化列表。
  2. 基类(S1)中的初始化列表。
  3. 基类(S0)中的构造函数主体。
  4. 派生类(S0)的构造函数主体。

在第2步之后,该对象被认为已足够构造以进行虚拟调度工作(即,要调用派生类中的重写)。 (这与C ++等语言不同,在C ++中,对象是纯粹从基类构造到派生类的,并且不允许在构造函数中进行虚拟调度,以防止在未构造的对象上调用方法。)

答案 1 :(得分:1)

因为在构造函数主体中允许访问此(及其成员)。因此,getter和setter是在执行构造函数之前生成的。

根据instance variable

所有实例变量都会生成一个隐式的getter方法。非最终实例变量也会生成隐式setter方法。

,并在Dart Programming Language Specification第10.8.1章继承和覆盖中进行了描述

实例变量从不相互替代。的吸气剂和二传手 实例变量。

因此,当您在S0类中调用this.a时,它已被子类S1覆盖;