変数の理解


「可変性」(Variant)は、クラス階層に及ぼす形式パラメータの影響を表します.次の3つのタイプに分けられます.
TがT`の上位資料型である場合

コトリンは無変性をデフォルト値とした.次の異常が発生する可能性があります.
    val strs: MutableList<String> = mutableListOf()
    
    val objs: MutableList<Any> = strs 
    // !!! A compile-time error here saves us from a runtime exception later

    objs.add(1) // Here we put an Integer into a list of Strings

    val s: String = strs[0] // !!! ClassCastException: Cannot cast Integer to String
上記のコードのMutableListがMutableListのサブタイプである場合、4番目のコードではIntをStringに鋳造できないため、例外が発生します.従って、運転時の安全性においては、無変性が基礎となる.
しかし、不変性のみを原則とすると、共通変数と逆共通変数が必要な場合にコードを記述する際に使用される不要なコード(例えば、タイプ鋳造)が長くなるため、Cottlinはoutとinキーワードを提供してこの問題を解決する.

[図]共通および逆共通の例

outとinの使用上の注意事項をコードで理解します.
outキーワードはin位置(Tタイプをパラメータとする)で作成できません.以下のコードに注記されています.
class Producer<out T: Music>(private var piece: T) {
    fun producePiece(): T = piece
  //fun setPiece(piece: T) { !! out으로 선언된 T는 in 위치에 나타날 수 없습니다 !!
  //    this.piece = piece
  //}
}

open class Music

class Metal : Music()

fun main() {
    val soundOfMusic = Music()

    val ultraMen = Metal()

    var person1 = Producer<Music>(soundOfMusic)
    var person2 = Producer<Metal>(ultraMen)

    // person2 = person1  !! type mismatch !!
}
in位置で使えるなら、person 2.これは、setPiece(SoundOfMusic)のようなコードを記述することができ、生産者がSoundOfMusicの生産者になるためである.

逆に、inキーを使用すると、out位置でのTの使用は禁止されます(Tタイプとその親タイプを返します).
class Consumer<in T>(private var source: T) {
  //fun produceSource(): T = source !! in으로 선언된 T는 out 위치에 나타날 수 없습니다 !!
    fun setSource(source: T) {
        this.source = source
    }
}

open class Vegetable

class Bamboo : Vegetable()

fun main() {
    val broccoli = Vegetable()

    val longBamboo = Bamboo()

    var vegeConsumer = Consumer<Vegetable>(broccoli)
    var bamboConsumer = Consumer<Bamboo>(longBamboo)

    vegeConsumer.setSource(longBamboo) // vegeConsumer can consume longBamboo
    //panda.setSource(broccoli) !! type mismatch !!
    
}
ConsumerオブジェクトはTタイプしか消費できないので、生産できません.

実際、上図のように、現実の生活では「consumerofplacelbeがどのようにconsumerof竹のサブ資料型になっているのか」という疑問が生じる可能性があります.
ただし、子データ型が親データ型の特例ではなく、子データ型が親データ型を継承し、子データ型から親データ型を受け入れる方法と手順を理解することができます.
この文章は以下の住所の文章を参考にして書いたものです.
ref1 : https://kotlinlang.org/docs/reference/generics.html
ref2 : https://proandroiddev.com/understanding-type-variance-in-kotlin-d12ad566241b
これは私の理解に基づいて書いた文章です.事実と異なる可能性があることを示す.
いつでもコメントでフィードバックを歓迎します