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 属性覆盖
子类需要重写父类的某些函数时,可以如下操作:
- 父类/父类方法 使用open修饰
- 子类使用
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 的是一个子类对象,也是调用父类的扩展方法,这跟多态是不一样的。当扩展方法在贬义词出现歧义时,只会根据形参类型选择扩展函数
如果类中已经定义了一个函数,然后静态扩展了一个同名同形参函数,扩展函数会失效(类中原本定义的函数优先级更高)