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

猜你喜欢

转载自blog.csdn.net/jingerlovexiaojie/article/details/107089521
今日推荐