Et le débutant de Kotlin demande: "Pourquoi le code suivant ne compilera-t-il pas?":
var left: Node? = null
fun show() {
if (left != null) {
queue.add(left) // ERROR HERE
}
}
La conversion intelligente vers 'Node' est impossible, car 'left' est une propriété modifiable qui aurait pu être modifiée à ce moment
J'obtiens que left
c'est une variable mutable, mais je vérifie explicitement left != null
et left
est de type Node
alors pourquoi ne peut-il pas être casté intelligemment dans ce type?
Comment puis-je résoudre ce problème avec élégance? :)
n.left?.let { queue.add(it) }
je pense?Réponses:
Entre l'exécution de
left != null
etqueue.add(left)
un autre thread aurait pu changer la valeur deleft
ennull
.Pour contourner cela, vous avez plusieurs options. Voilà quelque:
Utilisez une variable locale avec une conversion intelligente:
Utilisez un appel sécurisé tel que l'un des suivants:
Utilisez l' opérateur Elvis avec
return
pour revenir tôt de la fonction englobante:Notez que
break
etcontinue
peut être utilisé de manière similaire pour les vérifications dans les boucles.la source
Node
classe définie dans la version originale de la question qui avait un extrait de code plus compliqué avecn.left
au lieu de simplementleft
. J'ai mis à jour la réponse en conséquence. Merci.val
pour chacunvar
, imbriquer plusieurs?.let
instructions ou utiliser plusieurs?: return
instructions en fonction de votre fonction. par exempleMyAsyncTask().execute(a1 ?: return, a2 ?: return, a3 ?: return)
. Vous pouvez également essayer l'une des solutions pour une «location de variables multiples» .1) Vous pouvez également utiliser
lateinit
Si vous vous faites votre initialisation plus tardonCreate()
ou ailleurs.Utilisez ceci
Au lieu de cela
2) Et il y a une autre façon d'utiliser la
!!
fin de variable lorsque vous l'utilisez comme cecila source
Il y a une quatrième option en plus de celles de la réponse de mfulton26.
En utilisant l'
?.
opérateur, il est possible d'appeler des méthodes ainsi que des champs sans traiterlet
ou utiliser des variables locales.Du code pour le contexte:
Il fonctionne avec des méthodes, des champs et toutes les autres choses que j'ai essayé de faire fonctionner.
Ainsi, afin de résoudre le problème, au lieu d'avoir à utiliser des transtypages manuels ou à l'aide de variables locales, vous pouvez utiliser
?.
pour appeler les méthodes.Pour référence, cela a été testé dans Kotlin
1.1.4-3
, mais également testé dans1.1.51
et1.1.60
. Il n'y a aucune garantie que cela fonctionne sur d'autres versions, cela pourrait être une nouvelle fonctionnalité.L'utilisation de l'
?.
opérateur ne peut pas être utilisée dans votre cas car c'est une variable transmise qui est le problème. L'opérateur Elvis peut être utilisé comme alternative, et c'est probablement celui qui nécessite le moins de code. Au lieu d'utilisercontinue
cependant,return
pourrait également être utilisé.L'utilisation de la coulée manuelle peut également être une option, mais ce n'est pas sans danger:
Ce qui signifie que si la gauche a changé sur un autre thread, le programme plantera.
la source
left
et nonqueue
. Besoin de vérifier cela, modifiera la réponse dans une minuteLa raison pratique pour laquelle cela ne fonctionne pas n'est pas liée aux threads. Le fait est que cela
node.left
est effectivement traduit ennode.getLeft()
.Cet getter de propriété peut être défini comme suit:
Par conséquent, deux appels peuvent ne pas retourner le même résultat.
la source
Remplacez
var left: Node? = null
parlateinit var left: Node
. Problème résolu.la source
Faites ceci:
Ce qui semble être la première option fournie par la réponse acceptée, mais c'est ce que vous recherchez.
la source
Pour qu'il y ait une conversion intelligente des propriétés, le type de données de la propriété doit être la classe qui contient la méthode ou le comportement auquel vous souhaitez accéder et NON que la propriété soit du type de la super classe.
par exemple sur Android
Être:
Solution:
Usage:
GL
la source
Votre solution la plus élégante doit être:
Ensuite, vous n'avez pas à définir de variable locale nouvelle et inutile, et vous n'avez pas de nouvelles assertions ou transtypages (qui ne sont pas DRY). D'autres fonctions de portée peuvent également fonctionner, alors choisissez votre préférée.
la source
Essayez d'utiliser l'opérateur d'assertion non nul ...
la source
Comment je l'écrirais:
la source