Наследование Kotlin

В Kotlin все классы наследуются от класса Any. Он является суперклассом всех классов и суперклассом по умолчанию для классов без явного указания супертипа:

class Example // 从 Any 隐式继承

Any по умолчанию предоставляет три функции:

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("Example", 18, "S12346", 89)
    println("学生名: ${s.name}")
    println("年龄: ${s.age}")
    println("学生号: ${s.no}")
    println("成绩: ${s.score}")
}

Вывод:

学生名: Example
年龄: 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("Example", 18, "S12345", 89)
}

Вывод:

-------基类次级构造函数---------
-------继承类次级构造函数---------
学生名: Example
年龄: 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();

}

Вывод:

I am in college.

Если есть несколько одинаковых методов (унаследованных или реализованных из других классов, например классов 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. Чтобы устранить неоднозначность, функция должна вызвать реализации этой функции в A() и B() и предоставить собственную реализацию.

Вывод:

AB

Переопределение свойств

Переопределение свойств использует ключевое слово override. Свойства должны иметь совместимые типы. Каждое объявленное свойство может быть переопределено инициализатором или геттером:

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

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

Можно переопределить свойство val свойством var, но не наоборот. Поскольку свойство val само определяет геттер, переопределение его как свойства var дополнительно объявляет сеттер в производном классе.

Вы можете использовать ключевое слово override в основном конструкторе как часть объявления свойства:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}
Другие расширения