定义一个基础抽象类:BaseClass
abstract class BaseClass {
var a = getLevel()
val b = a++
val c:Int
init {
c = a++
}
val d = a++
abstract fun getLevel(): Int
fun print() {
println("a: $a, b: $b, c: $c, d: $d")
println("level: ${getLevel()}")
}
}
定义一个继承抽象类的实体类:AClass
// 函数定义隐含构建方法
class AClass: BaseClass() {
override fun getLevel(): Int {
return 0
}
}
或者:
class AClass: BaseClass {
// 声明构建方法继承自 BaseClass()
constructor(): super()
override fun getLevel(): Int {
return 0
}
}
执行代码:
AClass().print()
打印结果:
a: 3, b: 0, c: 1, d: 2
level: 0
可知,在构造方法的执行中,init函数和声明 按代码顺序依次执行。即 BaseClass 的初始化过程也可视为:
abstract class BaseClass {
var a:Int
val b:Int
val c:Int
val d:Int
init {
// 初始化在 init 之前
a = getLevel()
b = a++
// init 中执行
c = a++
// 初始化在 init 之后
d = a++
}
abstract fun getLevel(): Int
open fun print() {
println("a: $a, b: $b, c: $c, d: $d")
println("level: ${getLevel()}")
}
}
子类的初始化顺序
当子类中,也有需要初始化的属性时
class AClass: BaseClass() {
val f = a++
override fun getLevel(): Int {
return 0
}
override fun print() {
super.print()
println("f: $f, a: $a")
}
}
子类print 方法是 BaseClass 方法的重写,因而 BaseClass 的print 方法需要添加 open 关键字
open fun print() {
println("a: $a, b: $b, c: $c, d: $d")
println("level: ${getLevel()}")
}
打印结果:
a: 3, b: 0, c: 1, d: 2
level: 0
f: 3, a: 4
可知,在构造方法的执行中,会先执行父类的初始化,然后再执行子类的初始化。即 AClass 的初始化过程也可视为:
class AClass {
var a:Int
val b:Int
val c:Int
val d:Int
val f: Int
init {
// 父类的初始化
a = 0
b = a++
c = a++
d = a++
// 子类的初始化
f = a++
}
}
改变子类属性的声明位置
class AClass: BaseClass {
// 先声明属性,再定义构建函数
val f = a++
constructor(): super()
override fun getLevel(): Int {
return 0
}
override fun print() {
super.print()
println("f: $f, a: $a")
}
}
打印结果不变,说明 子类构建方法执行时,必先执行父类构建方法,与声明位置无关
当父类的初始化依赖于子类的属性
class AClass(private val level: Int): BaseClass() {
val f = a++
override fun getLevel(): Int {
// level 为子类构建函数中的值
// 期待先赋值 level,再执行 BaseClass 中的数据初始化
return level
}
override fun print() {
super.print()
println("f: $f, a: $a")
}
}
运行代码:
AClass(10).print()
期望运行结果:
a: 13, b: 10, c: 11, d: 12
level: 10
f: 13, a: 14
实际运行结果:
a: 4, b: 0, c: 1, d: 2
level: 10
f: 3, a: 4
从结果可知,在初始化时,level 并没有被赋值为10,依旧是0 (a 的取值由 0 开始)
子类属性初始化在父类之前
如果希望子类属性初始化先于父类,需要将父类的初始化变为一个普通函数,由子类初始化调用。代码修改为:
// 父类
abstract class BaseClass {
var a = 0
var b = 0
var c = 0
var d = 0
fun initBase() {
a = getLevel()
b = a++
c = a++
d = a++
}
abstract fun getLevel(): Int
open fun print() {
println("a: $a, b: $b, c: $c, d: $d")
println("level: ${getLevel()}")
}
}
// 子类:
class AClass(private val level: Int): BaseClass() {
val f = a++
init {
// init 中调用父类的数据初始化
initBase()
}
override fun getLevel(): Int {
return level
}
override fun print() {
super.print()
println("f: $f, a: $a")
}
}
输出结果
a: 13, b: 10, c: 11, d: 12
level: 10
f: 0, a: 13
似乎哪里不大对?f 的数据并不是期待的13,而是 0?
因为 f 的声明位置在 init 函数之前,所以取 a++ 时,a 为 0
再次修改子类为:
class AClass(private val level: Int): BaseClass() {
init {
initBase()
}
// 先定义 init 函数,再声明 f
val f = a++
override fun getLevel(): Int {
return level
}
override fun print() {
super.print()
println("f: $f, a: $a")
}
}
输出结果:
a: 13, b: 10, c: 11, d: 12
level: 10
f: 13, a: 14