Kotlin 継承

Kotlin ではすべてのクラスが Any クラスを継承します。Any はすべてのクラスのスーパークラスであり、スーパータイプの宣言がないクラスにとってはデフォルトのスーパークラスです。

class Example // 从 Any 隐式继承

Any はデフォルトで 3 つの関数を提供します。

equals()

hashCode()

toString()

注意: Any は java.lang.Object ではありません。

クラスを継承できるようにするには、open キーワードで修飾します。

open class Base(p: Int)           // 定义基类

class Derived(p: Int) : Base(p)

コンストラクタ

サブクラスにプライマリコンストラクタがある場合

サブクラスにプライマリコンストラクタがある場合、基底クラスはプライマリコンストラクタ内で直ちに初期化する必要があります。

open class Person(var name : String, var age : Int){// 基类

}

class Student(name : String, age : Int, var no : String, var score : Int) : Person(name, age) {

}

// 测试
fun main(args: Array<String>) {
    val s =  Student("サンプル", 18, "S12346", 89)
    println("学生名: ${s.name}")
    println("年龄: ${s.age}")
    println("学生号: ${s.no}")
    println("成绩: ${s.score}")
}

出力結果:

学生名: サンプル
年龄: 18
学生号: S12346
成绩: 89

サブクラスにプライマリコンストラクタがない場合

サブクラスにプライマリコンストラクタがない場合、各セカンダリコンストラクタで super キーワードを使って基底クラスを初期化するか、または別のコンストラクタに委譲する必要があります。基底クラスを初期化する際は、基底クラスの異なるコンストラクタを呼び出すことができます。

class Student : Person {

    constructor(ctx: Context) : super(ctx) {
    } 

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx,attrs) {
    }
}

例

/**用户基类**/
open class Person(name:String){
    /**次级构造函数**/
    constructor(name:String,age:Int):this(name){
        //初始化
        println("-------基类次级构造函数---------")
    }
}

/**子类继承 Person 类**/
class Student:Person{

    /**次级构造函数**/
    constructor(name:String,age:Int,no:String,score:Int):super(name,age){
        println("-------继承类次级构造函数---------")
        println("学生名: ${name}")
        println("年龄: ${age}")
        println("学生号: ${no}")
        println("成绩: ${score}")
    }
}

fun main(args: Array<String>) {
    var s =  Student("サンプル", 18, "S12345", 89)
}

出力結果:

-------基类次级构造函数---------
-------继承类次级构造函数---------
学生名: サンプル
年龄: 18
学生号: S12345
成绩: 89

オーバーライド

基底クラスで fun を使って関数を宣言する場合、その関数はデフォルトで final 修飾され、サブクラスでオーバーライドできません。サブクラスによるオーバーライドを許可するには、手動で open を追加して修飾する必要があります。サブクラスは override キーワードでメソッドをオーバーライドします。

/**用户基类**/
open class Person{
    open fun study(){       // 允许子类重写
        println("我毕业了")
    }
}

/**子类继承 Person 类**/
class Student : Person() {

    override fun study(){    // 重写方法
        println("我在读大学")
    }
}

fun main(args: Array<String>) {
    val s =  Student()
    s.study();

}

出力結果は次のとおりです。

私は大学に通っています。

同じメソッドが複数ある場合(他のクラスから継承または実装、例: A、B クラス)、そのメソッドをオーバーライドする必要があります。super ジェネリクスを使って、親クラスの実装を選択的に呼び出します。

open class A {
    open fun f () { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } //接口的成员变量默认是 open 的
    fun b() { print("b") }
}

class C() : A() , B{
    override fun f() {
        super<A>.f()//调用 A.f()
        super<B>.f()//调用 B.f()
    }
}

fun main(args: Array<String>) {
    val c =  C()
    c.f();

}

C が a() または b() から継承する場合、C は A または B から関数を継承できるだけでなく、A()、B() に共通する関数も継承できます。このとき、その関数は C 内にただ 1 つの実装しかありません。曖昧さを排除するために、その関数は A() と B() 内のその関数の実装を呼び出し、独自の実装を提供する必要があります。

出力結果は次のとおりです。

AB

プロパティのオーバーライド

プロパティのオーバーライドには override キーワードを使用します。プロパティは互換性のある型でなければなりません。宣言された各プロパティは、初期化子または getter メソッドによってオーバーライドできます。

open class Foo {
    open val x: Int get { …… }
}

class Bar1 : Foo() {
    override val x: Int = ……
}

var プロパティで val プロパティをオーバーライドすることはできますが、その逆はできません。val プロパティは getter メソッドを定義しているだけなので、var プロパティにオーバーライドすると、派生クラスに setter メソッドが追加で宣言されることになります。

プライマリコンストラクタ内で、プロパティ宣言の一部として override キーワードを使用できます。

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}
その他の拡張