Herencia de Kotlin

En Kotlin, todas las clases heredan de la clase Any, que es la superclase de todas las clases, y es la superclase predeterminada para las clases sin una superclase declarada:

class Example // 从 Any 隐式继承

Any proporciona tres funciones por defecto:

equals()

hashCode()

toString()

Nota: Any no es java.lang.Object.

Si una clase debe ser heredada, se puede modificar con la palabra clave open.

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

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

Constructor

La subclase tiene un constructor principal

Si la subclase tiene un constructor principal, la clase base debe inicializarse de inmediato en el constructor principal.

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

Resultado:

学生名: Ejemplo
年龄: 18
学生号: S12346
成绩: 89

La subclase no tiene constructor principal

Si la subclase no tiene un constructor principal, debe inicializar la clase base con la palabra clave super en cada constructor secundario, o delegar en otro constructor. Al inicializar la clase base, se puede llamar a diferentes constructores de la clase base.

class Student : Person {

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

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

Ejemplo

/**用户基类**/
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("Ejemplo", 18, "S12345", 89)
}

Resultado:

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

Anulación

En la clase base, cuando se declara una función con fun, esta función está decorada como final por defecto y no puede ser anulada por la subclase. Si se permite que la subclase anule la función, entonces se debe agregar manualmente open para modificarla. La subclase usa la palabra clave override para anular el método:

/**用户基类**/
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();

}

Resultado:

Estoy en la universidad.

Si hay varios métodos iguales (heredados o implementados de otras clases, como las clases A y B), entonces se debe anular ese método, usando super genérico para llamar selectivamente a la implementación de la clase padre.

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 hereda de a() o b(); C no solo puede heredar funciones de A o B, sino que también puede heredar las funciones comunes de A() y B(). En este momento, la función tiene solo una implementación en C; para eliminar la ambigüedad, la función debe llamar a las implementaciones de esa función en A() y B(), y proporcionar su propia implementación.

Resultado:

AB

Anulación de propiedades

La anulación de propiedades usa la palabra clave override; las propiedades deben tener tipos compatibles. Cada propiedad declarada puede ser anulada mediante un inicializador o un método getter:

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

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

Puedes anular una propiedad val con una propiedad var, pero no al revés. Porque una propiedad val define un método getter por sí misma; anularla como una propiedad var declarará adicionalmente un método setter en la clase derivada.

Puedes usar la palabra clave override en el constructor principal como parte de la declaración de la propiedad:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}
Otras extensiones