Dart 为什么可以';我不能把一个数字转换成双精度的吗?

Dart 为什么可以';我不能把一个数字转换成双精度的吗?,dart,google-cloud-firestore,flutter,Dart,Google Cloud Firestore,Flutter,weight是一个字段(中的数字),设置为100 int weight = json['weight']; double weight = json['weight']; int-weight工作正常,按预期返回100,但double-weight崩溃(Object.noSuchMethod异常),而不是返回100.0,这是我预期的 然而,以下工作: num weight = json['weight']; num.toDouble(); 当从Firestore解析100时(Firestor

weight
是一个字段(中的数字),设置为
100

int weight = json['weight'];
double weight = json['weight'];
int-weight
工作正常,按预期返回
100
,但
double-weight
崩溃(
Object.noSuchMethod
异常),而不是返回
100.0
,这是我预期的

然而,以下工作:

num weight = json['weight'];
num.toDouble();

当从Firestore解析
100
时(Firestore实际上不支持“数字类型”,但是),按照标准,它将被解析为
int

Dart不会自动“巧妙地”投射这些类型。事实上,您不能将
int
转换为
double
,这是您面临的问题。如果可能的话,您的代码就可以正常工作

解析 相反,您可以自己解析它:

double weight = json['weight'].toDouble();
铸造 同样有效的是,将JSON解析为
num
,然后将其分配给
double
,这将
num
转换为
double

double weight = json['weight'] as num;
起初这似乎有点奇怪,事实上(例如,内置于VS代码和IntelliJ的Dart插件中)会将其标记为“不必要的强制转换”
,而事实并非如此

double a = 100; // this will not compile

double b = 100 as num; // this will compile, but is still marked as an "unnecessary cast"
double b=100 as num
编译,因为即使没有显式强制转换,Dart也会将超级强制转换为子类型。
显式演员阵容将如下所示:

double a = 100 as double; // does not compile because int is not the super class of double

double b = (100 as num) as double; // compiles, you can also omit the double cast
关于“省道中的类型和铸造”

解释 发生在你身上的事情如下:

double weight;

weight = 100; // cannot compile because 100 is considered an int
// is the same as
weight = 100 as double; // which cannot work as I explained above
// Dart adds those casts automatically

在Dart中,
int
double
是独立的类型,都是
num
的子类型

数字类型之间没有自动转换。如果你写:

num n = 100;
double d = n;
您将得到一个运行时错误。Dart的静态类型系统允许不安全的向下转换,因此
n
d
的不安全分配(不安全,因为并非所有
num
值都是
double
值)被隐式视为:

num n = 100;
double d = n as double;
as double
检查该值是否实际为
double
(或
null
),如果不是,则抛出。如果该检查成功,则可以安全地将该值分配给
d
,因为已知该值与变量的类型匹配

这就是这里发生的事情。
json['weight']
(可能是静态类型的
对象
动态对象
)的实际值是值为100的
int
对象。将其分配给
int
有效。将其分配给
num
有效。将其分配给
double
将抛出

Dart JSON解析器将没有小数或指数部分的数字解析为整数(
0.0
是双精度,
0e0
是双精度,
0
是整数)。这在大多数情况下都非常方便,但在像您这样需要
double
但创建JSON的代码没有将其作为double编写的情况下,有时会让人恼火

在这种情况下,提取值时只需在值上写入
.toDouble()
。这对真正的双打来说是不可能的


另外,编译为JavaScript的Dart将所有数字表示为JavaScript数字类型,这意味着所有数字都是双倍的。在JS编译的代码中,所有整数都可以赋值为double而无需转换。如果代码运行在非JS实现上(如Flatter、Dart VM/server或iOS的提前编译),则这将不起作用,因此不要依赖它,否则您的代码将无法移植。

您可以解析如下所示的数据:

这里的文档是一张
地图


只需像这样将
int
转换为
double

int a = 10;
double b = a + 0.0;

您可以在一行中完成:

 double weight = (json['weight'] as num).toDouble();

double-weight=json['weight'].toDouble()
?您可以这样做:
double-weight=json['weight']+0.0这是飞镖,而不是飞镖本身。Dart对打字要求非常严格。最终,它使代码更清晰。但需要一点时间来适应它——Dart不仅仅是为您神奇地转换变量。这基本上是错误的。Dart从不将整数值转换为双精度,您必须调用
.toDouble()
。对一个数字进行
转换不会改变其类型。如果运行
double x=42作为numint
@lrn的实例也可以工作。我在发帖前测试了一下。。你也可以查看我链接的内容。我可能误读了你写的内容,如果是,我道歉。我对您所说的工作原理感到非常困惑(当在VM上运行时,
.toDouble()
工作,其他一切都不工作,但从文本中看不清楚,这些示例不应该工作)。“解析”部分实际上是从int转换为double,“转换”部分所做的事情在运行时都失败了。所以,也许我只是说消息不清楚。不确定您指的是哪个链接,但我对Dart类型的系统和运行时行为非常熟悉。我是从Dart 2静态和运行时类型系统的角度讲的,但我在这里所说的也适用于
--checked
more中的Dart 1(它检查类型,而不是忽略它们并允许任何操作)。您不会得到运行时错误。我不知道你是从哪里弄来的。也许曾经是这样,但是你可以在虚拟机上试试。没有编译或运行时错误。仅尝试:
main(){num n=100;double d=n;}
在Dart 2虚拟机上运行会产生
未处理的异常:类型“int”不是类型“double”的子类型
。将
添加为double
没有任何区别。分配过去在未经检查的Dart 1代码中工作,但如果在运行Dart 1时使用
--checked
,它将以完全相同的方式失败。An double weight = (json['weight'] as num).toDouble();