Um zu verstehen, warum es sinnvoll ist, IttayD provided a nice explanation:
Was würden wir gern haben, ist def orNull[A >: Null] = .....
Aber A ist bereits festgelegt und wir wollen nicht beschränken Sie es in der Definition der Eigenschaft. Daher erwartet orNull einen Hinweis, dass A ein Nullable Typ ist. Dieser Nachweis ist in Form einer implizite Variable (daher der Name ‚ev‘)
Zusammengefasst sind Typ Einschränkungen nützlich, wenn Sie Methoden wollen (zB orNull
) auf einer generischen Klasse (zB Option
) mit spezifischeren Randbedingungen (zB Null <: A <: Any
) als auf der Klasse selbst (zB A <: Any
).
Dies ist ein weiteres "Feature", das nicht in die Sprache integriert ist, sondern dank impliziter Parameter und Varianzanmerkungen von Typparametern kostenlos zur Verfügung steht. Um dies zu verstehen, Blick auf die Definition von <:<
:
// from Predef
sealed abstract class <:<[-From, +To] extends (From => To)
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x}
Für
scala> Some(1).orNull
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int]
Some(1).orNull
der Compiler sucht nach einem impliziten Wert vom Typ <:<[Null, Int]
und das Verfahren def conforms[A]: A <:< A
finden. Es muss also eine A
sein, für die <:<[Null, Int]
entspricht. Es gibt keine A
für die dies gilt und der Compiler wird sich über den fehlenden impliziten Wert beschweren.
jedoch für
scala> Some("hi").orNull
res21: java.lang.String = hi
haben wir Glück. Nun versucht der Compiler, eine A
zu finden, für die <:<[A, A]
<:<[Null, String]
entspricht. Dies funktioniert für A = String
, weil Null
ist ein Untertyp von String
und der From
Typ Parameter der Klasse <:<
ist als kontravariante definiert). Wie erwähnt, ist die intuitivste Art, über Typabhängigkeiten nachzudenken, das Lesen derselben wie eine Typgrenze (d.h. Lesen als Null <: Int). Null
entspricht nicht Int
und es gibt keinen impliziten Wert für <: < [Null, Int]. Auf der anderen Seite entspricht Null
String
und der Compiler findet den impliziten Parameter.
Übrigens, hier ist ein weiterer related answer.
Ach, der Quellcode verwendet 'Null <: