在kotlin定义范型时,有时会使用到in out关键字。网上很多文章都有介绍这两个关键字的使用,越看越迷糊,比如以下边的食物、快餐、汉堡、食物商店,快餐店、汉堡店为例子:
很不理解为什么下边的几行代码前两行会编译通过,而后一个会出错。
val consumer1: Consumer<Burger> = FoodConsumer() val consumer2: Consumer<Burger> = FastFoodConsumer() val consumer3: Consumer<Food> = BurgerConsumer()//compile error
以最后一行代码为例, 换一个角度想,在通过val consumer3: Consumer<Food>来声明一个变量时,就是告诉编译器后来对该变量的使用都要严格遵守他的类型约定,比如consumer3他的类型是Consumer<Food>,那么他调用consume方法时,就必须传入Food参数。而consumer3由于是饮用变量,实际传给他的对象是一个BurgerConsumer对象,该对象里边的consumer方法能接受的参数只能接收Burger类型,所以这就出现了变量的声明跟实际情况不符的情况,显然通过下边的方法调用consumer3的consume()方法会报错。依次类推,用同样方式可以解释为什么其他情况。
val food = Food()
consumer3.consume(food)
完整代码示例如下:
interface Producer<out T>{
fun produce(): T
}
interface Consumer<in T>{
fun consume(item: T)
}
open class Food
open class FastFood: Food()
class Burger: FastFood()
class FoodStore: Producer<Food>{
override fun produce(): Food {
println("Produce one food!")
return Food()
}
}
class FastFoodStore: Producer<FastFood>{
override fun produce(): FastFood {
println("produce one fastfood!!")
return FastFood()
}
}
class BurgerFoodStore: Producer<Burger>{
override fun produce(): Burger {
println("Produce one burger!!")
return Burger()
}
}
class FoodConsumer: Consumer<Food>{
override fun consume(item: Food) {
println("Consume one food!")
}
}
class FastFoodConsumer: Consumer<FastFood>{
override fun consume(item: FastFood) {
println("Consume one fastfood")
}
}
class BurgerConsumer: Consumer<Burger>{
override fun consume(item: Burger) {
println("Consume one burger")
}
}
fun main(){
val producer: Producer<Food> = FoodStore()
val producer1: Producer<Food> = FastFoodStore()
val producer2: Producer<Food> = BurgerFoodStore()
val producer3: Producer<Burger> = BurgerFoodStore()
// val producer4: Producer<Burger> = FoodStore()//compile error
// val producer5: Producer<Burger> = FastFoodStore()//compile error
val consumer1: Consumer<Burger> = FoodConsumer()
val consumer2: Consumer<Burger> = FastFoodConsumer()
val consumer3: Consumer<Food> = BurgerConsumer()//compile error
}