这和协变是不相容的: 如果一个协变类型参数(out) 出现在 in 所修饰的位置(例如函数的入参),通过协变和向上转化,我们可以传递任何想要的类型,显然这是不安全的,因为值的类型是非常具体的类型,所以当它的类型是 Dog 时,它不能去存一个 String
这种情况是不安全的,因为在类型转化之后,实际的对象还是不变的,只是类型系统对其可以进行不同的处理。 我们试图将 Int 设置进来,但是我们只能设置一个 Dog,如果这可以通过编译的话,我们肯定会出现错误。 这就是为什么 Kotlin 通过禁止在一个 public 的 in 修饰的地方使用有协变修饰符的参数来防止这种情况出现。
class Cup<in T>
open class Dog
class Puppy(): Dog()
fun main(args: Array<String>) {
val b: Cup<Dog> = Cup<Puppy>() // Error
val a: Cup<Puppy> = Cup<Dog>() // OK
val anys: Cup<Any> = Cup<Int>() // Error
val nothings: Cup<Nothing> = Cup<Int>() // OK
}
fun printProcessedNumber(transition: (Int)->Any) {
print(transition(42))
}
val intToDouble: (Int) -> Number = { it.toDouble() }
val numberAsText: (Number) -> Any = { it.toShort() }
val identity: (Number) -> Number = { it }
val numberToInt: (Number) -> Int = { it.toInt() }
val numberHash: (Any) -> Number = { it.hashCode() }
printProcessedNumber(intToDouble)
printProcessedNumber(numberAsText)
printProcessedNumber(identity)
printProcessedNumber(numberToInt)
printProcessedNumber(numberHash)
open class Dog
class Puppy: Dog()
class Hound: Dog()
fun takeDog(dog: Dog) {}
takeDog(Dog())
takeDog(Puppy())
takeDog(Hound())
class Box<out T> {
private var value: T? = null
// Illegal in Kotlin
fun set(value: T) {
this.value = value
}
fun get(): T = value ?: error("Value not set")
}
val puppyBox = Box<Puppy>()
val dogBox: Box<Dog> = puppyBox
dogBox.set(Hound()) // But I have a place for a Puppy
val dogHouse = Box<Dog>()
val box: Box<Any> = dogHouse
box.set("Some string") // But I have a place for a Dog
box.set(42) // But I have a place for a Dog
class Box<out T> {
var value: T? = null // Error
fun set(value: T) { // Error
this.value = value
}
fun get(): T = value ?: error("Value not set")
}
class Box<out T> {
private var value: T? = null
private set(value: T) {
this.value = value
}
fun get(): T = value ?: error("Value not set")
}
fun append(list: MutableList<Any>) {
list.add(42)
}
val strs = mutableListOf<String>("A", "B", "C")
append(strs) // Illegal in Kotlin
val str: String = strs[3]
print(str)
sealed class Response<out R, out E>
class Success<out R>(val value: R): Response<R, Nothing>()
class Failure<out E>(val error: E): Response<Nothing, E>()
open class Car
interface Boat
class Amphibious: Car(), Boat
fun getAmphibious(): Amphibious = Amphibious()
val car: Car = getAmphibious()
val boat: Boat = getAmphibious()