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泛型來說,我們可以將父類型對象賦給子類型引用