Please explain use of Option's orNull method

后端 未结 5 940
北荒
北荒 2021-02-01 21:29

Scala\'s Option class has an orNull method, whose signature is shown below.

orNull [A1 >: A](implicit ev : <:<[Null, A1]) : A1
5条回答
  •  误落风尘
    2021-02-01 21:38

    scala> Some(1).orNull
    :10: error: could not find implicit value for parameter ev: <:<[Null,Int]
           Some(1).orNull
                   ^
    scala> (None : Option[Int]).orNull
    :10: error: could not find implicit value for parameter ev: <:<[Null,Int]
           (None : Option[Int]).orNull
    
    scala> Some("hi").orNull
    res21: java.lang.String = hi
    
    scala> Some(null : String).orNull
    res22: String = null
    
    scala> (None : Option[String]).orNull
    res23: String = null
    

    To explain the implicit thing: orNull is a way of getting back from the Some|None idiom to Java's value|null idiom (which is, of course, bad). Now only AnyRef values (instances of classes) can accept a null value.

    So what we would have liked is def orNull[A >: Null] = ..... But A is already set and we don't want to restrict it in the definition of the trait. Therefore, orNull expects an evidence that A is a nullable type. This evidence is in the form of an implicit variable (hence the name 'ev')

    <:<[Null, A1] can be written as Null <:< A1 seeing it like this, it is similar to 'Null <: A1'. <:< is defined in Predef as well as the method that provides the implicit value named conforms.

    I think the use of A1 is not strictly required here and is because orNull uses getOrElse (where the default given can be a super type of A)

    scala> class Wrapper[A](option: Option[A]) {
         | def orNull(implicit ev: Null <:< A): A = if(option.isEmpty) null else option.get
         | }
    defined class Wrapper
    
    scala> new Wrapper(Some("hi")).orNull
    res18: java.lang.String = hi
    

提交回复
热议问题