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?
Utilisez null
en dernier recours. Comme déjà mentionné, Option
remplace la plupart des utilisations de null. Si vous utilisez null
pour implémenter l'initialisation différée d'un champ avec un calcul coûteux, vous devez utiliser un lazy val
.
Cela dit, Scala supporte null
. Personnellement, je l'utilise en combinaison avec Spring Dependency Injection.
Votre code est parfaitement valide. Cependant, je vous suggère d'utiliser var t: T = _
pour initialiser t
à sa valeur par défaut. Si T
est une primitive, vous obtenez la valeur par défaut spécifique au type. Sinon, vous obtenez null
.
Non seulement ceci est plus concis, mais il est nécessaire quand vous ne savez pas à l'avance ce que sera T
:
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
Utiliser var t: T= null
est une erreur de compilation si T n'est pas lié:
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 preuve que T
est nullable - un sous-type de AnyRef
n'est pas un sous-type de NotNull
Ce n'est pas entièrement baked , même dans Scala 2.8.
scala> class A[T](implicit ev: Null <:< T) { var t: T = null }
defined class A
La réponse canonique est n'utilisez pas null . Au lieu de cela, utilisez 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)
}
Comme David et retronym l'ont déjà mentionné, c'est une bonne idée d'utiliser Option
dans la plupart des cas, car Option
rend plus évident le fait que vous devez gérer une situation sans résultat. Cependant, renvoyer Some(x)
nécessite la création d'un objet et appeler .get
ou .getOrElse
peut coûter plus cher qu'une instruction if. Ainsi, dans le code haute performance, utiliser Option
n'est pas toujours la meilleure stratégie (en particulier dans le code de recherche de collection, où vous pouvez rechercher une valeur très souvent et ne pas vouloir en conséquence de nombreuses créations d'objet). Là encore, si vous faites quelque chose comme retourner le texte d’une page Web entière (qui n’existera peut-être pas), il n’ya aucune raison que not n’utilise pas Option.
En outre, juste pour ajouter au commentaire de retronym sur les génériques avec null
, vous pouvez le faire de manière complètement cuite si vous voulez vraiment dire que ce 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 la méthode <:<
, car elle n'obéit pas à NotNull
autant que je sache, mais elle fait exactement ce que vous espériez.
Je suis tombé sur cette question car scalastyle m'a dit de ne pas utiliser null lors de l'initialisation d'un objet dans mon test avec null
.
Ma solution sans changer aucun type qui satisfasse scalastyle:
var a: MyObject = (None: Option[MyObject]).orNull