Kotlin継承とマルチステート(2)マルチステート、is、as

3372 ワード

  • 多態概念
  • isと!is型検査
  • asとasを使用しますか?型変換を行う
  • 一、多態概念
    マルチステートの発生には、次の3つの前提条件があります.
  • 継承.マルチステートは、必ず子と親の間で発生します.
  • 書き換え.子クラスは親クラスの関数を書き換えます.
  • は、オブジェクトタイプが親タイプであり、オブジェクトが子クラスのインスタンスであることを宣言します.
  • open class Figure {
        open fun onDraw() {
            println("   Figure ...")
        }
    }
    
    class Ellipse : Figure() {
        override fun onDraw() {
            println("   Ellipse ...")
        }
    }
    
    class Triangle : Figure() {
        override fun onDraw() {
            println("   Triangle ...")
        }
    }
    
    fun main(args: Array) {
        val f1 = Figure()
        f1.onDraw() //    Figure ...
    
        val f2: Figure = Ellipse() // 1️⃣
        f2.onDraw() //    Ellipse ...
    
        val f3: Figure = Triangle() // 2️⃣
        f2.onDraw() //    Triangle ...
    
        val f4 = Triangle()
        f2.onDraw() //    Triangle ...
    }
    

      実行結果から分かるコード第1️⃣、2️⃣ローがマルチステート条件を満たすとマルチステートが発生し、マルチステートが発生すると、Kotlinは実行時に参照変数が指すインスタンスに基づいてその関数を呼び出すのではなく、参照変数のタイプに基づいて呼び出す.
    二、isと!isタイプチェック
    obj is type    // obj   type    ,   true
    obj !is type   // obj    type    ,   true
    

    kotlinでオブジェクトがタイプに属しているかどうかを判断する場合、isと!is演算子.
    open class Person(val name: String, val age: Int)
    
    class Student(name: String, age: Int, private val school: String) : Person(name, age)
    
    class Worker(name: String, age: Int, factory: String) : Person(name, age)
    
    fun main(args: Array) {
        val student1 = Student("  ", 18, "    ")
        val student2 = Student("  ", 18, "    ")
        val student3 = Student("  ", 18, "    ")
    
        val worker1 = Worker("  1", 20, "  ")
        val worker2 = Worker("  2", 20, "  ")
    
        val people = arrayOf(student1, student2, student3, worker1, worker2)
    
        var studentNum = 0
        var workerNum = 0
    
        people.forEach {
            when (it) {
                is Student -> studentNum++
                is Worker -> workerNum++
            }
        }
    
        println("    :$workerNum,     :$studentNum")    //     :2,     :3
        println(worker2 !is Worker) // false
        println(0 is Int)   // true
    }
    

    三、asとasを使う?タイプ変換
    リファレンスタイプ変換には2つの方向があります.親リファレンスタイプ変数をサブクラスタイプに変換します.この変換をダウンシフトと呼びます.サブクラス参照タイプ変数を親タイプに変換します.この変換をアップシフトと呼びます.ダウンシフトにはasまたは!as演算子は強制変換を行う.アップグレードは自動的で、asや!asは、もちろん使えます.
    fun main(args: Array) {
        val p1: Person = Student("  ", 18, "    ")
        val p2: Person = Worker("  1", 20, "  ")
        
        val p3: Person = Person("  ", 18)
    
        val p4 = Student("  ", 18, "    ")
        val p5 = Worker("  2", 20, "  ")
    }
    

    上記のコードの変換タイプテーブル:
    オブジェクト
    Personタイプ
    Workerタイプ
    Sudentタイプ
    説明
    p1
    サポート
    サポートされていません
    サポート(ダウンシフト)
    タイプ:Personインスタンス:Studio
    p2
    サポート
    サポート(ダウンシフト)
    サポートされていません
    タイプ:Personインスタンス:Worker
    p3
    サポート
    サポートされていません
    サポートされていません
    タイプ:PersonインスタンスPerson
    p4
    サポート(アップグレード)
    サポートされていません
    サポート
    タイプ:Studioインスタンス:Studio
    p5
    サポート(アップグレード)
    サポート
    サポートされていません
    タイプ:WorkerインスタンスWorkerインスタンスWorker
      注意:as演算子を使用して強制変換中に、タイプが互換性がないとランタイム異常が発生し、ClassCasException異常が放出されます.asを使うなら?演算子は変換され、タイプが互換性がない場合は空の値を返し、異常は放出されないのでas?演算子は、「安全な変換」演算子と呼ばれます.