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泛型来说,我们可以将父类型对象赋给子类型引用