Kotlin 中所有类都有一个共同的父类 Any. 如果没有显式声明父类, 都会隐式默认继承它
class Example // Implicitly inherits from Any
Any
并不是java.lang.Object
. 它除了 equals(), hashCode() 与 toString()
外没有任何成员
要显示声明父类, 可以把父类的构造函数放在类头的冒号后面:
open class BaseA
class DerivedA: BaseA()
Kotlin 中的类默认都是不被基层的, 相当于 java 中的 final class
. 如果想要被继承,
可以在前面使用 open
关键字"打开封印".
也可以用次构造函数:
open class BaseB(val a: Int, val b: Int?, val c: Int) {
constructor(a: Int, c: Int): this(a, null, c)
}
// 使用父类的用次构造函数也是可以的
class DerivedB(a: Int, b: Int?, c: Int, val d: Int, val e: Int): BaseB(a, c)
/*
会生成这样的构造函数:
public DerivedB(int a, @Nullable Integer b, int c, int d, int e) {
super(a, c);
this.d = d;
this.e = e;
}
*/
派生类没有主构造函数, 使用次构造函数继承的情况:
// 如果派生类没有主构造函数
class DerivedBB: BaseB {
// 因为属性必须初始化, 所以写上 getter
// 没有必要写 setter, 会自动生成
var d: Int
get() = field
var e: Int
get() = field
// 使用次构造函数继承父类, 得用 super 关键字
constructor(a: Int, b: Int?, c:Int, d: Int, e:Int): super(a, b, c) {
this.d = d
this.e = e
}
constructor(a: Int, c: Int, d: Int, e: Int): super(a, c) {
this.d = d
this.e = e
}
重写方法(overriding)
方法的重写也需要再父类中"打开封印", 因为方法也是默认 public final
的.
open class BaseC {
open fun funC() {
println("funC")
}
}
class DerivedC: BaseC() {
override fun funC() {
// super.funC()
println("重写后的 funC")
}
}
fun main(args: Array<String>) {
val derivedC = DerivedC()
derivedC.funC()
}
标记为 override
后, 改方法本身就变成 open
的了, 可以用 final
再次禁止重写.
重写属性
跟重写方法一样, 重写属性也需要 open
关键字然后再 override
:
open class BaseD {
open var d: Int = 0
// 这个是没有 backing field 的
open val dd get() = true
}
class DerivedD: BaseD() {
override var d: Int = 1
override var dd = false
}
调用父类方法及属性
可以使用 super
调用父类的方法和属性的实现.
open class BaseE {
open fun funE() { println("BaseE.funE()") }
open val e get() = 1
}
class DerivedE: BaseE() {
override fun funE() {
super.funE()
println("DerivedE.funE()")
}
override val e get() = super.e + 1
}
内部类想调用外部内的父类方法属性可以用 super@Outer
语法实现:
class DerivedE: BaseE() {
override fun funE() {
super.funE()
println("DerivedE.funE()")
}
override val e get() = super.e + 1
inner class InnerE {
fun f() {
super@DerivedE.funE()
println(super@DerivedE.e)
}
}
}
继承规则
如果一个类继承了多个直接超类(父类和接口), 并且这些父类中有同名的成员(属性或方法), 同名成员必须
重写实现; 需要调用不同父类的同名成员, 使用 super<父类>
来区别.
open class BaseF {
open fun f() {
println("BaseF.f()")
}
open val f get() = "BaseF.f"
}
interface IBaseG {
// 接口中的方法和属性默认都是 open 的
// 接口可以有实现代码
fun f() {
println("IBaseG.f()")
}
val f get() = "IBaseG.f"
}
class DerivedFG: BaseF(), IBaseG {
override fun f() {
super<BaseF>.f()
super<IBaseG>.f()
}
override val f get() = super<BaseF>.f + super<IBaseG>.f
}
抽象类
一个类中只要有一个抽象方法(abstract
标记的, 没有实现代码的方法), 那么这个类就
是抽象类, 也必须用 abstract
标记.
可以用抽象类的抽象方法去继承重写非抽象类的方法:
open class BaseH {
open fun f() {}
}
abstract class DerivedH : BaseH() {
override abstract fun f()
}
伴生对象
Kotlin 中没有 static
静态方法, 大部分情况下都推荐使用包级函数来代替.
还有一种情况, 如果不用类实例对象来调用, 但又需要访问类内部(比如工厂方法), 那就
需要在类中写一个"对象声明"(object declaration), 准确的说应该是需要声明一个"伴生
对象"(companion object).
class MyClass {
// 可以省略伴生类的类名
companion object {
fun create(): MyClass = MyClass()
}
}
然后可以这样去用(很像 static
方法):
val instance = MyClass.create()
网友评论