これは、最初のコンパイルと2番目のコンパイルがなぜコンパイルされないのか理解するのに苦労しているコードです。
class Test11<T : Number> {
lateinit var test: MutableList<out T>.() -> Unit
}
fun main() {
val test: Test11<Int> = Test11<Int>()
val test2: Test11<out Number> = test
test.test.invoke(MutableList(3) { 55 }) // First
test2.test.invoke(MutableList(3) { 55 }) // Second
}
2番目の発言MutableList<Nothing>
は予想されていた。
だから、基本的には最初のケースでは、T => Int
そのうちout T => out Int => out Number
多分。2番目のケースT => out Number
では、Numberのサブクラスであるものは何でも、それでもout T => out Number
正しいですか?
なぜそのロジックで動作しないのか理解できません...
MutableListは関数パラメーターです。あなたはまったく同じ問題を抱えているでしょう:
class Test11<T : Number> {
fun test(list: MutableList<out T>) {
}
}
fun main() {
val test: Test11<Number> = Test11<Number>()
val test2: Test11<out Number> = test
test.test(MutableList(3) { 55 }) // First
test2.test(MutableList(3) { 55 }) // Second
}
定義上、共分散型は、型がパラメーターである関数が呼び出されないようにしますが、これは論理的には同じ型のネストされた共分散にも拡張されます。Tが(クラスに対して)共変である場合、Tを直接消費するよりも、Tを生成できるオブジェクトを消費する方が安全ではありません。
これがどのように失敗を引き起こす可能性があるかの例:
class Test11<T : Number> {
var list: MutableList<out T>? = null
fun test(list: MutableList<out T>) {
this.list = list
}
}
fun main() {
val test: Test11<Long> = Test11()
val test2: Test11<out Number> = test
val doubleList: MutableList<out Number> = mutableListOf(1.0)
test2.test(doubleList) // Not allowed
// if it were allowed:
val long: Long? = test.list?.firstOrNull() // ClassCastException casting the Double to a Long
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加