Dart TypeError: тип не является подтипом типа Null - PullRequest
0 голосов
/ 26 мая 2020

Рассмотрим следующий код:

void printInt(int i) => print(i);
void printString(String s) => print(s);

void printSomething(Object o) {
  final printer = {
    int: printInt,
    String: printString,
  }[o.runtimeType];
  print('Printer is $printer');
  printer(o);
}

void main() => printSomething('Hello');

Он печатает правильную printString функцию, а затем вылетает со следующим исключением:

TypeError: "Hello": type 'String' is not a subtype of type 'Null'

Почему это происходит?

1 Ответ

1 голос
/ 26 мая 2020

Ошибка возникает из-за того, что вашей карте присвоен тип Map<Type, void Function(Null)>, поскольку это единственный тип, который она может использовать в зависимости от содержимого вашего списка.

Проблема в том, что Dart не может дать ваша карта другого типа, поскольку все остальное не будет действительным с точки зрения системы типов. Допустим, тип был Map<Type, void Function(Object)>. Что ж, тогда нам разрешено отправить любой объект в метод из этой карты. Но это недопустимо, так как ваши два метода на карте четко определены как принимающие int и String, а не Object.

Мы можем либо присвоить ему тип Map<Type, void Function(int)>, поскольку у нас есть метод, принимающий String.

Кроме того, Map<Type, void Function(dynamic)> имеет ту же проблему, что и Object, поскольку оба метода четко определены для получения точного типа.

Так что Dart вместо этого будет использовать Null в качестве типа параметра, поскольку единственное, что, как мы знаем, допустимо для предоставления обоих методов, - это значение null.

И поскольку вы затем пытаетесь передать String в качестве параметра методу с сигнатурой void Function(Null) вы получаете сообщение об ошибке от системы типов.

Если вы хотите, чтобы ваш код запускался, вам нужно указать системе типов, чтобы она не знала, что вы делаете. Для этого вы должны использовать dynamic для типа метода, который вы получаете от карты:

void printInt(int i) => print(i);
void printString(String s) => print(s);

void printSomething(Object o) {
  final dynamic printer = {
    int: printInt,
    String: printString,
  }[o.runtimeType];
  print('Printer is $printer');
  printer(o);
}

void main() => printSomething('Hello');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...