ユーザ用ツール

サイト用ツール


サイドバー

kotlin:共変_反変

以前のリビジョンの文書です


共変_反変

Kotlinの場合
不変(Array)…同じ型でなければならない。(そもそもlistは不変ではない)

共変(out)…上位の型に下位の型を入れることが出来る。
 設定といっても初期値(val)として。
 取り出す(参照)ときには上位の型として取り出す。

反変(in)…下位の定義を上位の定義を設定できる。
 設定とはvar変数に値をいれること。
 参照するときは上位の型として参照する。
 

不変

fun main() {
 
    // --- 不変 ... 同じ型でなければならない ---
 
    // listは不変ではない
    val intList = listOf<Int>(1, 2, 3)
    val anyList: List<Any> = intList
 
 
    // 配列は不変
    val intArray = Array<Int>(3,{index -> index})
    //    val anyArray:Array<Any> = intArray // 方が違うのでコンパイルエラー

共変(out)

valとして変更しない、参照用(out)として値を設定する
上位のAny型に、下位のint型を設定しているが、Any型として参照しかしない(out)ので安全。

    // --- 共変(out) ... 広い定義に狭い定義のものを参照用に入れることが出来る(val)  ---
    // --- 提供するだけ 戻り値として広い定義を使用できる
    val intArray2 = Array<Int>(3,{index -> index})
    val anyArray2:Array<out Any?> = intArray2  // outがないとコンパイルエラー
    val tmp2 = anyArray2[2]  // outとしてはAny?型となる
    if(tmp2 is Any?){
        println("temp2 is Any")
    }else{
        println("temp2 is not Any")
    }
     ↓
  temp2 is Any

反変(in)

varの値を変更する。
下位のHuman型の配列に、上位のAnimal型の配列を設定しているが、Animal型としてしか参照しないので安全。

    // --- 反変 ...
    val intArray3 = Array<Int>(3,{index -> index*3})
    var anyArray3:Array<in Int> = intArray3
    anyArray3.forEach { println("anyArray3=${it}")}
 
    // --- 反変2 クラス これはできて当たり前
    open class Animal(val name:String){
        open fun Cry(){println("${name}!!")}
    }
    class Human(name:String):Animal(name){
        override fun Cry(){println("I'm${name}")}
    }
 
    val animal:Animal = Human("Takeshi")  // クラスは共変
    animal.Cry()
 
    // --- 反変2 クラス配列 これが本当の反変
    val humanArray:Array<in Human> = Array(1, {i -> Animal("Gray")}) // Human型にAnimalが入る
//   val animal2:Human = humanArray[0] as Human // Human型だとコンパイルでエラーとなる
//    animal2.Cry() // エラーとなる
 
    val animal3:Animal = humanArray[0] as Animal // Animal型だと取り出せる。
    animal3.Cry() // Animal型として使える
}
kotlin/共変_反変.1574697458.txt.gz · 最終更新: 2019/11/26 00:57 by ips