#dart
Вопрос:
Вот пример из документа
В документе говорится, что целочисленные литералы автоматически преобразуются в двойные, когда это необходимо:
double z = 1; // Equivalent to double z = 1.0.
Но когда я проверяю runtimeType
тип, это int
print(z.runtimeType); // prints to int
Ответ №1:
Я предполагаю, что вы тестируете с помощью dartpad.dev или скомпилировали свой код на JavaScript. В JavaScript нет отдельных типов int
, и double
поэтому Dart просто угадывает тип при использовании runtimeType
на основе текущего значения, поскольку JavaScript представляет все числа как double
внутренние.
Но если мы работаем в виртуальной машине Dart или скомпилированы в машинный код, мы можем определить тип. Таким образом, ваш пример будет возвращен double
как тип z
, если он работает с виртуальной машиной Dart.
void main(List<String> args) {
print(1.1.runtimeType); // dartpad: double, dartvm: double
print(1.0.runtimeType); // dartpad: int, dartvm: double
print(1.runtimeType); // dartpad: int, dartvm: int
}
См. Также Примечание о различном поведении int
типа при компиляции в JavaScript в документации Dart:
https://api.dart.dev/stable/2.12.3/dart-core/int-class.html
Более подробный пример показан здесь, где мы можем увидеть, как double
объявленная переменная ведет себя по-разному при запуске кода Dart в DartVM против скомпилированного JavaScript:
void main(List<String> args) {
print('| toString | runtimeType | is int | is double |');
for (double i = 0; i <= 2; i = 0.5) {
print('| ${i.toString().padRight(8)} | '
'${i.runtimeType.toString().padLeft(11)} | '
'${(i is int).toString().padLeft(6)} | '
'${(i is double).toString().padLeft(9)} |');
}
}
Который возвращает следующее с помощью DartPad:
| toString | runtimeType | is int | is double |
| 0 | int | true | true |
| 0.5 | double | false | true |
| 1 | int | true | true |
| 1.5 | double | false | true |
| 2 | int | true | true |
В то время как ДартВМ возвращается:
| toString | runtimeType | is int | is double |
| 0.0 | double | false | true |
| 0.5 | double | false | true |
| 1.0 | double | false | true |
| 1.5 | double | false | true |
| 2.0 | double | false | true |
И int
мы можем сделать то же самое:
void main(List<String> args) {
print('| toString | runtimeType | is int | is double |');
for (int i = 0; i <= 2; i = 1) {
print('| ${i.toString().padRight(8)} | '
'${i.runtimeType.toString().padLeft(11)} | '
'${(i is int).toString().padLeft(6)} | '
'${(i is double).toString().padLeft(9)} |');
}
}
Дартс:
| toString | runtimeType | is int | is double |
| 0 | int | true | true |
| 1 | int | true | true |
| 2 | int | true | true |
ДартВМ:
| toString | runtimeType | is int | is double |
| 0 | int | true | false |
| 1 | int | true | false |
| 2 | int | true | false |
Комментарии:
1. Вы говорите, что JavaScript внутренне представляет все числа как двойные, тогда во всех ваших примерах тип на dartpad должен быть двойным, но это не так.
2. Я говорю, что
runtimeType
вы догадываетесь, каким был бы тип, если бы это был обычный код дротика. Это связано с тем, что у вас есть некоторые ожидания (как у программиста) относительно типов, когда вы программируете в Dart. Например, вы ожидаете aint
при добавлении двухint
объектов. Но за кулисами все числа всегдаdouble
находятся в JavaScript.3.Один из способов взглянуть на это-сказать, что все числа Dart являются
double
s при компиляции в JavaScript, но некоторые из них такжеint
являются s. Это похоже на то, как если бы объект number fori1
реализовывал иint
то, иdouble
другое одновременно (к счастью, интерфейсы совместимы). Если вы проверите1 is double
или1 is int
, оба дадутtrue
.runtimeType
Получатель должен лгать, нет реального класса, реализующего оба типа, поэтому он возвращаетсяint
, когда это возможно, аdouble
когда нет. На практике никогда ни для чего не используйтеruntimeType
!4. @lrn Ах да, забыл об этом. Обновил пример, чтобы добавить в него некоторые ваши данные. И да, «никогда
runtimeType
ни для чего не используйте!» нельзя говорить слишком часто (может быть, когда-нибудь это предупреждение будет добавлено в документацию API?) 🙂