[HeadFirst]Kotlinクラス継承

8386 ワード

superClass, subClass


スーパークラスは親、サブクラスは子を表します.この二つを結びつけると継承(継承)です.サブクラスには、スーパークラスのメソッドとプロパティがあります.

Any


Kotlinのすべてのクラスのスーパークラスの最上位にAny classが存在します.すなわち,Kotlinクラス継承体系の根といえる.Anyクラスはequals(),hashCode()およびtoString()メソッドを定義するため,kotlinクラスごとに3つのメソッドがある.

Inheritance


では、なぜ継承を使うのでしょうか.
アプリケーションが増加するにつれて、1つのクラスで各クラス間の重複コードを管理します.したがって、通常、共通コードはスーパークラスに存在する.

シナリオ設計の継承


継承システムの設計において最も基本的なものはIS−A,HAS−A分析である.例えば、hippo IS-A animalは、カバのスーパーレベルが動物であることを意味する.しかし、動物は必ずしもhippoの直属スーパークラスになる必要はありません.動物はカバの超一流であることができる.
台所と冷蔵庫はどうですか.二つは関係があるのに、IS-A関係ではありません.この時はkitchen HAS-A fridgeで見たほうが正確です.このとき、二人は関係を継ぐというより、台所類が冷蔵庫という属性を持っているほうが自然です.
IS-A分析には該当しませんが、コード重複を減らすために継承を使うのはいかがでしょうか.概念的に一致しない2つのオブジェクトを継承関係にマージするのは適切ではありません.2つの共通属性を持つ新しいオブジェクトを作成し、両方を継承します.

継承の実装


デフォルトではkotlinクラスは継承できない状態(final)です.継承可能クラスとして定義するにはopenというキーワードを使用する必要があります.コンパイラopen keywordもpropertyとメソッドの上書きターゲットであることを通知する必要があります.
サブクラスでスーパークラスからvalとして定義された変数を変更するには、openキーを追加する必要があります.これにより、サブクラスはoverrideキーワードで変更できます.
open class Animal {
    open val image = ""
    open val food = ""
    open val habitat = ""
    var hunger = 10

    open fun makeNoise() {
        println("make some noise")
    }

    open fun eat() {
        println("eat")
    }

    open fun roam() {
        println("roaming")
    }

    fun sleep() {
        println("ZZZZ...")
    }
}

one superClass


classを継承する場合は、スーパークラスは1つしかありません.複数のスーパークラスは不可能です.

override


継承されたクラスは:によって継承されます.
valはoverrideキーワードを使用して変更できます.varはinit定義値を使用する必要があります.initで値を定義していない場合は、サブクラスでは使用できません.
スーパークラスでvalとして定義されたプロパティは、オーバーライドによってvarとして再定義できます.
関数を上書きする場合は、関数パラメータを一致させ、関数の戻りタイプの互換性に注意してください.すなわち、戻りタイプまたはサブクラスタイプとして一致する必要があります.
cclass Hippo : Animal() {
    override var image = "hippo.jpg"
    override val food = "grass"
    override val habitat = "water"

    init {
        hunger = 11
    }

    override fun eat() { 
        if (hunger < 0) { 
            println("Hippo do not need to eat $food.")
            return 
        }
        
        println("The Hippo is eating $food")
        hunger-- 
    } 
}

val->var / var->val


スーパークラスからvalとして定義されたpropertyをvarに変更できます.これは、スーパークラスとサブクラスの間でプロトコルsuperClass 에서 할 수 있는것을 subClass 에서 할 수 있어야 한다を遵守するためである.
より詳細には、valとして宣言された変数で、コンパイラはデフォルトでgetterを追加します.サブクラスでvarに変換するのはsetterを追加するため、サブクラスでスーパークラスで実行可能なgetterを実行することができます.
逆に、スーパークラスでvarとして定義された変数をサブクラスからvalに置き換えることはできません.これは、スーパークラスで実行可能なsetterがサブクラスで実行できないためです.이 protocol 지켜져야 하는 이유는 다형성(polymorphism) 때문이다.
fun main() {
    val myAnimal: Animal = Hippo()
    myAnimal.eat() // The Hippo is eating grass
}
「スーパータイプ」(SuperClass)と宣言された変数にはサブクラスが必要であるため、プロトコルは守らなければなりません.
多形性については,他の文章の論述がより詳細である.kotlin多形位置決め

open & final


これらの規則に従ってHippoクラスはAnimalクラスを継承する.継承システムでは、一度に開いたpropertyで、メソッドのサブクラスで開いた状態を維持し続けます.finalキーワードに遭遇すると、サブクラスからfinalステータスになります.
スーパークラスでは、開いているプロパティまたはメソッドのみがサブクラスに使用されるわけではありません.オープン状態はオーバーライド可能な状態であると理解されるべきである.
開いていなくても、子クラスでこの属性、メソッドにアクセスできます.親スーパークラスで最初に上書きまたは宣言された属性、メソッドが表示されます.