Должен ли Дарт выводить типы членов класса? - PullRequest
1 голос
/ 10 ноября 2019

В Dart 2.6.0, когда я использую is для проверки типа переменной члена класса, блок условного кода не выводит тип.

В следующем коде метод show1() выдает ошибку: «Получатель 's2' не определен для класса 'C1'."Между тем, метод show2() прекрасно компилируется.

class C1 {
  C1(this.s1);
  String s1;
}

class C2 extends C1 {
  C2(String s1, this.s2) : super(s1);
  String s2;
}

class InferenceTest {
  InferenceTest(this.c);
  C1 c;

  void show1() {
    print(c.s1);
    if (c is C2) print(c.s2); // error
  }

  void show2(C1 c) {
    print(c.s1);
    if (c is C2) print(c.s2); // no error
  }
}

Это похоже на ошибку, но, похоже, я не должен был первым это заметить. Я столкнулся с проблемой при попытке сделать вывод на widget.myValue из состояния виджета.

Я нашел ошибку или есть что-то, чего я не понимаю?

(я бы нашелэто разумно в многопоточной среде, такой как Java, потому что значение c может измениться между тестом is и использованием c. Но я понимаю, что Дарт в основном предполагает один поток.) ​​

1 Ответ

3 голосов
/ 11 ноября 2019

Dart не продвигает типовые переменные экземпляра, только локальные переменные.

Когда вы проверяете, что локальная переменная имеет определенный тип, тогда программа может использовать переменную, как если бы она имела проверенный тип. с некоторыми оговорками, потому что язык должен быть абсолютно уверен, что значение не меняется между тестом и использованием. Например, не должно быть назначений переменной в области, защищаемой тестом, и не должно быть назначений переменной, захваченной в замыкании. Поскольку переменная является локальной, компилятор может убедиться, что этого достаточно, чтобы значение переменной не изменилось.

Переменная экземпляра c класса InferenceTest имеет тип C1. Существуют допустимые программы, в которых значение c может меняться между тестом c is C2 и использованием c.s2, и оно может быть изменено кодом из совершенно другой библиотеки, поэтому язык не осмеливается продвигать тип втот случай. Поэтому тип c по-прежнему C1 при доступе c.s2, и вы не можете получить доступ к s2.

. Если вы хотите повысить, попробуйте переместить значение в локальную переменную:

var c = this.c;
if (c is C2) print(c.s2);

Это работает, что вы также видите в своем методе show2, поскольку параметры функции являются локальными переменными и, следовательно, подвергаются продвижению типов.

...