52 votes

Est-ce la bonne façon d'initialiser les références nulles dans Scala?

Disons que j'ai une instance MyObject qui n'est pas initialisée:

 var a:MyObject = null
 

est-ce la bonne façon de l'initialiser à null?

64voto

retronym Points 35066

Alternatives

Utiliser null comme un dernier recours. Comme déjà mentionné, Option remplace la plupart des usages de la valeur null. Si vous utilisez null pour mettre en œuvre différée de l'initialisation d'un champ avec certains cher de calcul, vous devez utiliser un lazy val.

Canonique de l'initialisation à la valeur null

Cela dit, Scala prend en charge null. Personnellement, je les utiliser en combinaison avec le Printemps et l'Injection de Dépendance.

Votre code est parfaitement valide. Cependant, je vous suggère d'utiliser var t: T = _ pour initialiser t de sa valeur par défaut. Si T est un primitif, vous obtenez la valeur par défaut spécifiques au type. Sinon vous obtiendrez null.

Non seulement c'est plus concis, mais il est nécessaire lorsque vous ne savez pas à l'avance ce qu' T sera:

scala> class A[T] { var t: T = _ }
defined class A

scala> new A[String].t
res0: String = null

scala> new A[Object].t            
res1: java.lang.Object = null

scala> new A[Int].t   
res2: Int = 0

scala> new A[Byte].t
res3: Byte = 0

scala> new A[Boolean].t
res4: Boolean = false

scala> new A[Any].t   
res5: Any = null

Avancé

À l'aide de var t: T= null est une erreur de compilation si T est illimitée:

scala> class A[T] { var t: T = null }
<console>:5: error: type mismatch;
 found   : Null(null)
 required: T
       class A[T] { var t: T = null }

Vous pouvez ajouter un paramètre implicite, comme une preuve qu' T est nullable -- un sous-type d' AnyRef pas un sous-type d' NotNull Ce n'est pas complètement cuit, même en Scala 2.8, il suffit donc de les considérer comme une curiosité pour l'instant.

scala> class A[T](implicit ev: Null <:< T) { var t: T = null }           
defined class A

32voto

David Crawshaw Points 4842

La réponse canonique est de ne pas utiliser null . Utilisez plutôt un type d'option:

 var a = None : Option[MyObject]
 

Quand vous voulez le définir:

 a = Some(foo)
 

Et quand vous voulez le lire, testez None:

 a match {
  case None => Console.println("not here")
  case Some(value) => Console.println("got: "+value)
}
 

8voto

Rex Kerr Points 94401

Comme David et retronym l'avons déjà mentionné, c'est une bonne idée d'utiliser Option dans la plupart des cas, comme Option le rend plus évident que vous avez à gérer une pas de de résultat, la situation. Cependant, retournant Some(x) nécessite une création de l'objet, et en appelant .get ou .getOrElse peut être plus cher qu'un if. Ainsi, en haute-performance du code, à l'aide de Option n'est pas toujours la meilleure stratégie (en particulier dans la collection de code de recherche, où vous pouvez rechercher une valeur très nombreuses fois et ne veulent pas en conséquence de nombreuses créations objet). Et puis, si vous êtes en train de faire quelque chose comme de retourner le texte d'une page web entière (ce qui pourrait ne pas exister), il n'y a pas de raison de ne pas utiliser l'Option.

Aussi, juste pour ajouter à retronym point sur les médicaments génériques avec null, vous pouvez le faire dans un cadre entièrement cuit façon, si vous avez vraiment dire qu'il devrait être null:

class A[T >: Null] { var t: T = null }

et cela fonctionne en 2.7 et 2.8. C'est un peu moins général que l' <:< méthode, car elle ne veut pas obéir NotNull autant que je sache, mais il fait exactement le contraire de ce que vous pouvez espérer qu'il allait faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X