Ciò significa che l'opzione [Nothing] è un sottotipo di Option [Int] (a causa della covarianza), giusto?
Corretto. Option[Nothing]
è un Option[Int]
.
Ma con B>: A abbiamo detto che B deve essere un supertipo ?! Quindi, come possiamo ottenere un back int?
Non deve essere un super-tipo. Richiede solo A
come con limite inferiore. Il che significa che puoi ancora passare Int
a getOrElse
se A
è Int
.
Ma ciò non significa che non è possibile passare le istanze di una sottoclasse. Per esempio:
class A
class B extends A
class C extends B
scala> Option(new B)
res196: Option[B] = Some([email protected])
scala> res196.getOrElse(new C)
res197: B = [email protected]
scala> res196.getOrElse(new A)
res198: A = [email protected]
scala> res196.getOrElse("...")
res199: Object = [email protected]
posso ancora passare un'istanza di C
, perché C
può essere up-cast B
. Posso anche passare un tipo più in alto nell'albero dell'ereditarietà, e invece getOrElse
restituirà quel tipo. Se passo un tipo che non ha nulla a che fare con il tipo contenuto nello Option
, verrà inferito il tipo con il limite superiore. Nel caso precedente, è Any
.
Quindi perché il limite inferiore esiste? Perché non ha:
def getOrElse[B <: A](default: => B): B
Questo non funzionerà perché getOrElse
deve o restituire il A
che è contenuto nel Option
, o il default B
. Ma se restituiamo il A
e A
non è un B
, quindi il tipo non è valido.Forse, se getOrElse
restituito A
:
def getOrElse[B <: A](default: => B): A
Questo lavoro (se fosse davvero definito in questo modo), ma si sarebbe limitato dal tipo-limiti. Quindi, nel mio esempio precedente, è possibile passare solo B
o C
a getOrElse
su un Option[B]
. In ogni caso, questo non è come è nella libreria standard.
La libreria standard getOrElse
consente di passare qualsiasi cosa ad esso. Supponi di avere Option[A]
. Se passiamo un sottotipo di A
, viene trasmesso a A
. Se passiamo a A
, ovviamente questo va bene. E se passiamo qualche altro tipo, il compilatore deduce il limite superiore tra i due. In tutti i casi, il limite di tipo B >: A
è soddisfatto.
Perché getOrElse
consente di passare qualsiasi cosa, molti lo considerano molto complicato. Ad esempio si potrebbe avere:
val number = "blah"
// ... lots of code
val result = Option(1).getOrElse(number)
E questo verrà compilato. Avremo solo uno Option[Any]
che probabilmente causerà un errore da qualche parte lungo la linea.
Grazie, ma potresti fornire un esempio di quale tipo non saremmo in grado di passare a res196.getOrElse ... al momento, con questo esempio, non vedo il punto di avere un limite inferiore. O meglio per dire, ora non capisco cosa significhi che un tipo sia un limite inferiore ... – Marin
@Marin Puoi passare qualsiasi tipo a 'getOrElse'. Vedi la mia modifica. –
grazie! Penso di averlo capito ora. – Marin