#flutter #dart #types #dart-null-safety
Вопрос:
есть одна вещь, которую я не могу понять относительно нулевой безопасности в Dart, и это касается того, как безопасно извлекать значения из Map<String,dynamic>
(я прочитал FAQ из документов Dart).
В принципе, следующий код в дартпаде с включенной защитой от ошибок действителен:
void main() {
int i;
Map<String, dynamic> map = {"key": 1};
i = map["key"];
print(i);
}
Чего я не понимаю. Почему я могу назначить map["key"]
, чтобы i
компилятор не кричал на меня? Из документов:
Код по умолчанию должен быть безопасным. Если вы пишете новый код Dart и не используете явно небезопасные функции, он никогда не выдает ошибку с нулевой ссылкой во время выполнения.
Но именно это и происходит. Если в приведенном выше коде ключа нет на карте или он содержит какой-либо случайный тип, программа выйдет из строя во время выполнения, что, по-моему, никогда не должно происходить с нулевой безопасностью.
Меня это особенно интересует, так как я пишу приложение Flutter и не понимаю, как правильно десериализовать данные JSON, которые я получаю из БД ( try..catch
? Специальный синтаксис, например ??=
?). Несмотря на то, что у меня не включена функция «ненулевого» языка (я даже не могу писать int? val
, не получив предупреждения), компилятор, похоже, не возражает против того, что я присваиваю ненулевые значения ненулевым переменным, и с радостью завершит работу во время выполнения, если они будут равны нулю.
В принципе, мой вопрос касается не только нулевой безопасности, но и системы типов в целом, поскольку, насколько я понимаю, не должно быть возможности присвоить dynamic
значение int
переменной, но, очевидно, это работает Map
. Любое объяснение будет высоко оценено!
Комментарии:
1. У вас нет ошибки анализа, потому что у вас
Map
объявленыdynamic
значения. Поэтому егоoperator []
отдачаdynamic?
такая же, какdynamic
и .dynamic
Тип отключает статическую проверку типов и полностью полагается на проверки во время выполнения. Если вам нужна правильная ошибка анализа, объявите свойMap
с типом значения, не допускающим значения null (напримерMap<String, Object>
). (Возможно, анализатор должен распознать этот случай и настаивать на том, чтоi
он все равно должен быть аннулирован, но я не знаю, возможно ли это на самом деле.)2. Кроме того, если вы зададите
implicit-casts: false
в своемpubspec.yaml
файле, вы должны получить ошибку анализа оdynamic
int
назначении кому. (Я думал, что неявные приведения были неявно отключены с нулевой безопасностью, но, возможно, есть какое-то исключение для неявных приведенийdynamic
.)3. @jamesdlin За
implicit-casts: false
то , что вы ошибочно написалиpubspec.yaml
вместоanalysis_options.yaml
. Я думаю, что причина, по которой он неfalse
находится в null-безопасном Dart, может заключаться в том, что даже если вы уверены, что данные из вашего json не являются нулевыми, вам придется использоватьint? i = map['i'];
и впоследствии обрабатывать этоnull
. В некоторых случаях вам нужно такое поведение, а в некоторых-нет. Кстати, ваш первый комментарий заслуживает места в поле для ответов.
Ответ №1:
Динамическая переменная может содержать любой тип данных, ключевое слово «dynamic» используется, когда вы не знаете конкретный тип данных, который может быть возвращен.
и что ты на самом деле здесь делаешь:
i = карта[«ключ»];
присваивает «динамическую» переменную переменной «int», и поскольку в этом случае значение в паре ключ/значение вашей карты является целым числом, которое соответствует типу данных «int» переменной «i», оно не произойдет из-за вывода типа, выполненного во время выполнения, а не во время компиляции. если бы «динамическая» переменная была строкой, она бы вышла из строя во время выполнения из-за несоответствия типов. Надеюсь, это объяснимо.