Scala Covariance and Lower Type Bounds Explanation

前端 未结 4 1152
说谎
说谎 2021-02-02 00:41

I am trying to get my head around covariance in respect with methods creating new immutable types using lower bounds

class ImmutableArray[+T](item: T, existing:          


        
4条回答
  •  星月不相逢
    2021-02-02 01:11

    First question:

    I understand that the type parameter T can not be used in the append method as it violates the rules

    Well it can be used. S >: T simply means that if you pass in a type S that is equal to T or its parant, then S will be used. If you pass a type that is sublevel to T then T will be used.

    scala> class Animal
    defined class Animal
    
    scala> class Canine extends Animal
    defined class Canine
    
    scala> class Dog extends Canine
    defined class Dog
    
    scala> new ImmutableArray[Canine](new Canine)
    res6: ImmutableArray[Canine] = ImmutableArray@a47775
    
    scala> res6.append(new Animal)
    res7: ImmutableArray[Animal] = ImmutableArray@1ba06f1
    
    scala> res6.append(new Canine)
    res8: ImmutableArray[Canine] = ImmutableArray@17e4626
    
    scala> res6.append(new Dog)
    res9: ImmutableArray[Canine] = ImmutableArray@a732f0
    

    Above doing res6.append(new Dog) still gives you ImmutableArray of type Canine. And if you think in a way it makes complete sense as adding Dog to Canine Array will still keep the array Canine. But adding Animal to Canine Array makes it Animal as it can no longer be perfectly canine (can be molar or something).

    This is a perfect example on why it is usually known that contra-variant type declaration make it perfect for writes (your case) and co-variance for reads.

    In your example, I think the confusion might be because you are comparing S >: T to S super T (from java world). With S super T you are bound to have the argument type that is Super class of T and it does not allow you to pass an argument that is sub-type to T. In scala, the compiler takes care of this (thanks to type-inference).

提交回复
热议问题