Kotlin 泛型詳解

Kotlin:聲明處協變 ,在類型參數聲明處提供

Java:使用處協變,具體使用的時候才聲明協變

我們隨便定義一個泛型如下:

class B<T extends CharSequence>{
    
}

這個表示在實例化B的時候你提供的泛型T必須是CharSequence或者CharSequence的子類,這個和Java的使用處協變不是一回

事。我們說的使用處協變是下面這種形式

B<? extends ...>

兩種方式不要混爲一談。

舉個協變例子:

interface Producer<out T> {
    fun product(): T
}

T前面有out修飾,表示T是一個協變類型。如果泛型T是協變類型,那麼只能用於一個方法的返回類型。也就是說如果一個類裏面的泛型是協變類型,只能用於一個方法的返回類型。

可以看到product()方法的返回類型是T類型。這個T是不能作爲輸入類型(參數)的。

可以這麼記produce = output = out 生產者

舉個協變例子:

interface Consumer<in T> {
    fun consume(item: T)
}

如果泛型類只是將泛型類型作爲其方法的輸入類型(參數),那麼我們就可以使用in。

可以這麼記consumer = input  = in

還有一種是不變類型,上例子

interface ProducerCoonsumer<T> {
    fun produce(): T

    fun consume(item: T)
}

如果泛型同時將泛型類型作爲其方法的輸入類型與輸出類型,那麼我們就不能使用out與in來修飾泛型

再來個協變的例子

open class Fruit

open class Apple :Fruit()

class ApplePear :Apple()

interface Producer<out T> {
    fun product(): T
}

class FruitProducer : Producer<Fruit> {
    override fun product(): Fruit {
        println("Produce Fruit")
        return Fruit()
    }
}

class AppleProducer :Producer<Apple>{
    override fun product(): Apple {
        println("produce Apple")
        return Apple()
    }

}

class ApplePearProducer :Producer<ApplePear>{
    override fun product(): ApplePear {
        println("produce ApplePear")
        return ApplePear()
    }

}

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main7)
  
        val producer1: Producer<Fruit> = FruitProducer()
        val producer2: Producer<Fruit> = AppleProducer()
        val producer3: Producer<Fruit> = ApplePearProducer()

    }

對於out泛型來說,我們可以將子類型對象賦給父類型引用

看看逆變的例子

class Human : Consumer<Fruit> {
    override fun consume(item: Fruit) {
        println("consume Fruit")
    }
}

class Man :Consumer<Apple>{
    override fun consume(item: Apple) {
        println("consume Apple")
    }
}

class Boy :Consumer<ApplePear>{
    override fun consume(item: ApplePear) {
        println("consume ApplePear")
    }
}

interface Consumer<in T> {
    fun consume(item: T)
}

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main8)
        val consumer1: Consumer<ApplePear> = Human()
        val consumer2: Consumer<ApplePear> = Man()
        val consumer3: Consumer<ApplePear> = Boy()
    }
}

對於in泛型來說,我們可以將父類型對象賦給子類型引用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章