#dart
#dart
Вопрос:
void main() {
var foo = number as int; // Works
for (var bar in numbers as List<int>) {} // Run-time error
}
num get number => 0;
List<num> get numbers => [0];
Примечание: я не ищу решение, как заставить это работать. Вопрос в том, почему я не могу понизить List<num>
до List<int>
, когда список на самом деле является типом List<int>
.
Комментарии:
Ответ №1:
В этом случае ваш список неявляется List<int>
.
Значение списка генерируется
List<num> get numbers => [0];
Вы не указали тип в литерале списка, например <int>[0]
, поэтому тип списка будет выведен для вас.
Dart использует две части информации для определения этого типа:
- Тип контекста (то, что требуется контексту)
List<num>
. Не у всех выражений есть тип контекста, но у этого есть. - Типы элементов (что требуется для элементов), которые
int
.
Если есть тип контекста, он всегда выигрывает. Таким образом, предполагается, что ваш получатель:
List<num> get numbers => <num>[0];
Когда вы затем пытаетесь сделать numbers as List<int>
, это не удается, потому что a List<num>
не является List<int>
(подтипирование наоборот).
Для других людей, которые действительно ищут решение, вы можете либо преобразовать список в List<int>
, создав новый список или обернув его с помощью cast
, либо вы можете преобразовать отдельные элементы. Или вы можете принудительно выполнить неявное понижение. Во всех случаях код завершится ошибкой, если список в конечном итоге будет содержать не int
значение.
for (var bar in <int>[...numbers as List<dynamic>]) { ... }
for (var bar in numbers.cast<int>()) { ... }
for (int bar in numbers as List<dynamic>) { ... }
for (var bar in numbers) { ... bar as int ... }
Комментарии:
1. Вау, какое это было отличное объяснение! Сэр, в вашем 3-м решении, когда мы делаем
numbers as List<dynamic>
, эта часть считается улучшенной или пониженной? Все выражение является понижением, которое я знаю.2. Приведение из
numbers
вList<dynamic>
является приведением вверх. При повторении каждый элемент будет преобразован вint
изdynamic
. Это потенциально опасно, потому что вместо этого он не поймал быnumbers
значениеList<String>
. В настоящее время я мог бы только что сделатьfor (int bar in numbers) ...
, что неявно понизило бы каждый элемент сnum
наint
, но это перестанет работать, когда будет выпущена функция безопасности Null и все неявные понижения перестанут работать… кроме тех, изdynamic
.3. Понял, спасибо. Но скажите мне одну вещь, где я могу найти столько информации о Dart? Документы не охватывают то, что вы знаете. Единственный способ задать вопрос на SO и дождаться вашего ответа?
4. Этот ответ сочетает в себе языковые возможности (
<int>[...]
), библиотечные возможности (.cast
) и поведение системы типов (неявные сокращения). Каждый из них документируется индивидуально, либо в документации библиотеки платформы, в сообщении о выпуске языковой функции (или спецификации), либо в пояснении к системе типов Dart 2.0. У Dart нет единого монолитного языка библиотек текста введения к общим пакетам. Возможно, так и должно быть, но это довольно сложная задача.5. Я вижу ненужное предупреждение о приведении в этой строке
numbers as List<dynamic>
, хотя вы также не можете его удалить. Должен ли я создать проблему для этого?