12:kotlin类和对象 -- 继承

kotlin中的所有类都有一个共同的超类Any

kotlin 复制代码
class Example // 没有声明,但是默认实现Any类

Any有三个方法:equals()hashCode()toString()

默认情况下,kotlin类是final修饰的,所以它们不能被继承。要使一个类可继承,用open关键字修饰

kotlin 复制代码
open class Base

继承一个类

kotlin 复制代码
open class Base(p: Int)

class Derived(p: Int) : Base(p)	// 继承Base类

如果实现类有主构造函数,则必须在该主构造函数中根据其参数初始化基类。

如果实现类没有主构造函数,则每个次构造函数都必须使用super关键字初始化父类型,或者它必须委托给另一个构造函数来执行。请注意,在这种情况下,不同的次构造函数可以调用父类的不同构造函数

kotlin 复制代码
class MyView : View {
    constructor(ctx: Context) : super(ctx)

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

重写方法

如果想要方法能够被重写,需要使用open关键字修饰方法

kotlin 复制代码
open class Shape {
    open fun draw() { /*...*/ }	// 方法使用open修饰后可以被重写
    fun fill() { /*...*/ }
}

class Circle() : Shape() {
    override fun draw() { /*...*/ }	// kotlin中重写方法使用override关键字修饰
}

override修饰符在Circle.draw()中是必需的。如果缺少它,编译器将会报错。如果一个函数没有open修饰符,比如Shape.fill(),无论子类中是否使用override修饰符都不能定义fill()方法

override修饰的成员本身是open的。想禁止被重写可以使用final修饰

kotlin 复制代码
open class Rectangle() : Shape() {
    final override fun draw() { /*...*/ }
}

重写属性

属性的重写机制与方法的重写机制相同。重写时必须具有兼容的类型。

kotlin 复制代码
open class Shape {
    open val vertexCount: Int = 0
}

class Rectangle : Shape() {
    override val vertexCount = 4
}

可以使用var类型重写val类型,但反之不行。因为val属性本质上声明了一个get方法,重写为var后同时声明了一个set方法

主构造函数中的属性声明中使用override关键字

kotlin 复制代码
interface Shape {
    val vertexCount: Int
}

class Rectangle(override val vertexCount: Int = 4) : Shape 

class Polygon : Shape {
    override var vertexCount: Int = 0  
}

实现类初始化顺序

在构造实现类的新实例期间,父类初始化在实现类的初始化逻辑运行之前

kotlin 复制代码
open class Base(val name: String) {

    init { println("Base init") }

    open val size: Int =
        name.length.also { println("Base: $it") }
}

class Derived(
    name: String,
    val lastName: String,
) : Base(name.replaceFirstChar { it.uppercase() }.also { println("Base constructor: $it") }) {

    init { println("Derived init") }

    override val size: Int =
        (super.size + lastName.length).also { println("Derived: $it") }
}

fun main(){
    Derived("王大锤","大锤")
//    Base constructor: 王大锤
//    Base init
//    Base: 3
//    Derived init
//    Derived: 5
}

这意味着在执行父类构造函数时,实现类中声明或覆盖的属性尚未初始化。在父类初始化逻辑中使用这些属性(直接或间接)可能会导致不正确的行为或运行时失败。因此,在设计父类时,应避免在构造函数、属性初始化程序或init块中使用open成员

调用父类实现

kotlin 复制代码
open class Rectangle {
    open fun draw() { println("画圆") }
    val borderColor: String get() = "black"
}

class FilledRectangle : Rectangle() {
    override fun draw() {
        super.draw()
        println("上色")
    }

    val fillColor: String get() = super.borderColor
}

fun main(){
    val filledRectangle = FilledRectangle()
    filledRectangle.draw()
//    画圆
//    上色
}

在内部类中,使用super@外部类名可以访问外部类的父类

kotlin 复制代码
open class Rectangle {
    open fun draw() { println("画圆") }
    val borderColor: String get()= "黑色"
}

class FilledRectangle: Rectangle() {
    override fun draw() {
        val filler = Filler()
        filler.drawAndFill()
    }

    inner class Filler {
        fun drawAndFill() {
            [email protected]() // 调用Rectangle的draw()
            println("${[email protected]}") // 调用Rectangle中borderColor的get()方法
        }
    }
}
fun main(){
    val filledRectangle = FilledRectangle()
    filledRectangle.draw()
    // 画圆
    // 黑色
}

重写规则

如果实现或者继承的类或者接口中有同名方法,则可以使用super<父类名>指定是哪一个类

kotlin 复制代码
open class Rectangle {
    open fun draw() { /* ... */ }
}

interface Polygon {
    fun draw() { /* ... */ } // 接口中方法默认是open的
}

class Square() : Rectangle(), Polygon {

    override fun draw() { // 重写draw()方法
        super<Rectangle>.draw() // 调用Rectangle.draw()
        super<Polygon>.draw() // 调用Polygon.draw()
    }
}

因为RectanglePolygon类中都有draw()方法,为了消除歧义,需要在Square中重写draw()方法

相关推荐
岸芷漫步6 分钟前
Kotlin中协程的关键函数分析
kotlin
纳于大麓7 小时前
Kotlin基础语法五
android·开发语言·kotlin
移动开发者1号7 小时前
嵌套滚动交互处理总结
android·kotlin
移动开发者1号7 小时前
Android工程中FTP加密传输与非加密传输的深度解析
android·java·kotlin
yzpyzp21 小时前
Kotlin的MutableList和ArrayList区别
android·kotlin
帅次1 天前
Flutter Container 组件详解
android·flutter·ios·小程序·kotlin·iphone·xcode
帅次1 天前
Flutter setState() 状态管理详细使用指南
android·flutter·ios·小程序·kotlin·android studio·iphone
移动开发者1号1 天前
Compose列表项动画实现指南
android·kotlin
移动开发者1号1 天前
Compose与View系统互操作方案
android·kotlin
heeheeai2 天前
kotlin kmp 副作用函数 effect
kotlin·effect·kmp·副作用函数