web-dev-qa-db-fra.com

Pourquoi ne puis-je pas convertir un nombre en double?

weight est un champ (Number in Firestore ), défini comme 100.

int weight = json['weight'];
double weight = json['weight'];

int weight fonctionne bien, renvoie 100 comme prévu, mais double weight se bloque (Object.noSuchMethod exception) plutôt que de renvoyer 100.0, ce à quoi je m'attendais.

Cependant, les travaux suivants:

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

Lors de l'analyse 100 de Firestore (qui ne supporte en fait pas un "type de nombre", mais le convertit ), il sera par défaut analysé en un int.
Dart ne convertit pas automatiquement "intelligemment" ces types. En fait, vous ne pouvez pas convertir un int en double, ce qui est le problème auquel vous êtes confronté. Si c'était possible, votre code fonctionnerait très bien.

Analyse

Au lieu de cela, vous pouvez analyser vous-même:

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

Fonderie

Ce qui fonctionne également, c'est d'analyser le JSON en num puis de l'attribuer à un double, qui convertira num en double.

double weight = json['weight'] as num;

Cela semble un peu étrange au début et en fait le outil d'analyse Dart (qui est par exemple intégré dans le plugin Dart pour VS Code et IntelliJ) le marquera comme un "distribution inutile" , ce qui n'est pas le cas.

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 compile parce que num est la super classe de double et Dart convertit super en sous-types même sans transtypages explicites.
Une conversion explicite serait la suivante:

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

Voici une bonne lecture à propos de "Types et casting dans Dart".

Explication

Ce qui vous est arrivé est le suivant:

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
23

Vous pouvez analyser les données comme indiqué ci-dessous:

Voici le document est un Map<String,dynamic>

double opening = double.tryParse(document['opening'].toString());
1
Dishant Mahajan

Vous pouvez le faire en une seule ligne:

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

Dans Dart, int et double sont des types distincts, les deux sous-types de num.

Il n'y a pas de conversion automatique entre les types de numéros. Si vous écrivez:

num n = 100;
double d = n;

vous obtiendrez une erreur d'exécution. Le système de type statique de Dart autorise les rétrogradations non sécurisées, donc l'affectation non sécurisée de n à d (dangereuse car toutes les valeurs num ne sont pas des valeurs double) est traité implicitement comme:

num n = 100;
double d = n as double;

Le as doublevérifie que la valeur est bien un double (ou null), et lance si ce n'est pas le cas. Si cette vérification réussit, elle peut affecter la valeur à d en toute sécurité car elle est connue pour correspondre au type de variable.

Voilà ce qui se passe ici. La valeur réelle de json['weight'] (Probablement avec le type statique Object ou dynamic) est l'objet int avec la valeur 100. Affectant cela à int travaux. L'affecter à num fonctionne. L'affecter aux lancers double.

L'analyseur Dart JSON analyse les nombres sous forme d'entiers s'ils n'ont pas de parties décimales ou exposantes (0.0 Est un double, 0e0 Est un double, 0 Est un entier). C'est très pratique dans la plupart des cas, mais parfois ennuyeux dans des cas comme le vôtre où vous voulez un double, mais le code créant le JSON ne l'a pas écrit en double.

Dans de tels cas, il vous suffit d'écrire .toDouble() sur les valeurs lorsque vous les extrayez. C'est un no-op sur les doubles réels.

En remarque, Dart compilé en JavaScript représente tous les nombres en tant que type de numéro JavaScript, ce qui signifie que tous les nombres sont doubles. Dans le code compilé JS, tous les entiers peuvent être affectés au double sans conversion. Cela fonctionnera pas lorsque le code est exécuté sur une implémentation non JS, comme Flutter, Dart VM/server ou une compilation anticipée pour iOS, alors ne dépendez pas de cela, ou de votre le code ne sera pas portable.

0
lrn