kotlin in out 关键字理解

在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
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin语言中,`in`和`out`关键字用于泛型类型的声明,用于表示逆变和协变。 - `in`关键字表示逆变,用于限制泛型类型的下界。逆变意味着只能将泛型类型作为消费者使用,即只能从中读取数据,而不能修改或写入数据。逆变可以确保类型的安全性。在Kotlin中,`in`关键字可以用于函数参数、属性和类型别名的声明。 - `out`关键字表示协变,用于限制泛型类型的上界。协变意味着可以将泛型类型作为生产者使用,即可以从中读取数据,并且可以将其作为返回值返回。协变可以确保类型的安全性。在Kotlin中,`out`关键字可以用于函数返回类型、属性和类型别名的声明。 下面是一个示例,演示了Kotlin中的`in`和`out`的使用: ```kotlin // 定义一个接口 interface Animal { fun sound() } // 定义一个类实现Animal接口 class Dog : Animal { override fun sound() { println("Woof!") } } // 定义一个类实现Animal接口 class Cat : Animal { override fun sound() { println("Meow!") } } // 定义一个函数,使用in关键字限制泛型类型的下界 fun <T : Animal> makeSound(animals: List<in T>) { for (animal in animals) { animal.sound() } } // 定义一个函数,使用out关键字限制泛型类型的上界 fun <T : Animal> getAnimalSounds(animal: T): List<out T> { return listOf(animal) } // 创建Dog和Cat对象 val dog = Dog() val cat = Cat() // 调用makeSound函数,传入Dog和Cat对象的列表 makeSound(listOf(dog, cat)) // 调用getAnimalSounds函数,获取Dog和Cat对象的声音列表 val sounds = getAnimalSounds(dog) for (sound in sounds) { sound.sound() } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值