推荐答案
在 Kotlin 中,out 和 in 关键字用于泛型类型的变型(variance),分别表示协变(covariant)和逆变(contravariant)。
out关键字用于声明协变类型参数,表示该类型参数只能用于输出(即只能作为返回类型),不能用于输入(即不能作为参数类型)。协变类型参数通常用于生产者(Producer),即只读取数据的场景。in关键字用于声明逆变类型参数,表示该类型参数只能用于输入(即只能作为参数类型),不能用于输出(即不能作为返回类型)。逆变类型参数通常用于消费者(Consumer),即只写入数据的场景。
本题详细解读
协变(Covariant)与 out 关键字
协变允许子类型关系在泛型类型中得以保留。例如,如果 Dog 是 Animal 的子类,那么 List<Dog> 可以被视为 List<Animal> 的子类型。在 Kotlin 中,使用 out 关键字来声明协变类型参数。
class Box<out T>(val value: T) {
fun get(): T = value
// fun set(value: T) {} // 错误:不能将 T 作为参数类型
}
val dogBox: Box<Dog> = Box(Dog())
val animalBox: Box<Animal> = dogBox // 协变允许将 Box<Dog> 赋值给 Box<Animal>在上面的例子中,Box 类的类型参数 T 被声明为 out,表示 T 只能用于输出(即只能作为返回类型),因此 Box<Dog> 可以被视为 Box<Animal> 的子类型。
逆变(Contravariant)与 in 关键字
逆变允许父类型关系在泛型类型中得以保留。例如,如果 Dog 是 Animal 的子类,那么 Consumer<Animal> 可以被视为 Consumer<Dog> 的子类型。在 Kotlin 中,使用 in 关键字来声明逆变类型参数。
// www.javascriptcn.com code example
class Box<in T> {
fun set(value: T) {
// 设置值
}
// fun get(): T // 错误:不能将 T 作为返回类型
}
val animalBox: Box<Animal> = Box()
val dogBox: Box<Dog> = animalBox // 逆变允许将 Box<Animal> 赋值给 Box<Dog>在上面的例子中,Box 类的类型参数 T 被声明为 in,表示 T 只能用于输入(即只能作为参数类型),因此 Box<Animal> 可以被视为 Box<Dog> 的子类型。
总结
out关键字用于协变,表示类型参数只能用于输出,适用于生产者场景。in关键字用于逆变,表示类型参数只能用于输入,适用于消费者场景。
通过使用 out 和 in 关键字,Kotlin 提供了更灵活的类型系统,使得泛型类型在继承关系中的行为更加明确和安全。