【Kotlin 三】封装/继承/多态 属性覆盖 类的扩展

1.封装/继承/多态

1.1 封装

一般,我们将类的属性都声明为private,在类中通过暴露一部分public的方法来供外部读写对象属性

kotlin 复制代码
class Student (private var name: String) {
    fun getName(): String {
        return name
    }
    fun setName(name: String) {
        this.name = name
    }
}

1.2 继承

默认的Kotlin类是终态(不可继承)的,可以使用open标记可以被继承的类

1.2.1 初始化顺序

存在继承关系时,初始化一个子类对象的顺序为:

父类初始化 > 子类主构造函数 > 子类次要构造函数

1.2.2 属性覆盖

子类需要重写父类的某些函数时,可以如下操作:

  1. 父类/父类方法 使用open修饰
  2. 子类使用override关键字修饰要重写的方法
kotlin 复制代码
open class Student {
    open fun hello() = println("我会打招呼")
}

class ArtStudent : Student() {
    override fun hello() = println("哦哈哟")
}

可以使用is关键字判断某个对象是否是某个类的实现,类似于Java中的instance of

明确来了某个对象是哪个类以后,可以使用as关键字来强转

如果一个对象是可空类型(如Student?),可以使用as?进行强转,当对象为空时会直接返回一个null作为强转后的结果

2.类的扩展

常用的类扩展可以通过继承实现:子类可以在父类的基础上,通过定义更多的属性和方法来扩展父类的功能

Kotlin支持在类代码不对外开放/不能被继承的情况下,扩展类的功能,比如一些第三方类不向我们开放编辑权限,再或者本身就是Kotlin的一些基础类型(String)。这些类在Java语言中完全不能扩展,但是在Kotlin中可以

kotlin 复制代码
fun main() {
    val text = "1"
    text.test()
}

fun String.test() = "111"

类的扩展是静态的(相对于多态是动态来说的),比如下面这个例子

kotlin 复制代码
open class Father
class Son : Father()

fun Father.test() = "111"
fun Son.test() = "222"

fun printObject(s: Father) {
    println(s.test())
}

fun main() {
    printObject(Son())
}

// 打印结果:111

因为是静态扩展,所以即使传入 printObject 的是一个子类对象,也是调用父类的扩展方法,这跟多态是不一样的。当扩展方法在贬义词出现歧义时,只会根据形参类型选择扩展函数

如果类中已经定义了一个函数,然后静态扩展了一个同名同形参函数,扩展函数会失效(类中原本定义的函数优先级更高)

相关推荐
一只柠檬新2 小时前
Kotlin object单例到底是懒汉式还是饿汉式
android·kotlin
hsx66618 小时前
Kotlin 协程中的 Dispatchers
kotlin
每次的天空21 小时前
Android-重学kotlin(协程源码第二阶段)新学习总结
android·学习·kotlin
stevenzqzq21 小时前
Kotlin 中主构造函数和次构造函数的区别
android·kotlin
开发者如是说1 天前
言叶是如何对文件进行端到端加密的
android·kotlin·swift
小李飞飞砖1 天前
kotlin
开发语言·单例模式·kotlin
小李飞飞砖1 天前
kotlin中的冷流和热流
android·开发语言·kotlin
Kotlin上海用户组2 天前
Koin vs. Hilt——最流行的 Android DI 框架全方位对比
android·架构·kotlin
Kapaseker2 天前
当Object遇到Json你可能会碰到的坑
kotlin
RichardLai882 天前
Kotlin Flow:构建响应式流的现代 Kotlin 之道
android·前端·kotlin