1. 构造函数的分类
在 Kotlin 中,构造函数分为主构造函数和次构造函数,一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分:它跟在类名(与可选的类型参数)后。
class Person constructor(name: String) {
}
1.1 constructor
关键字
如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor
关键字。
open class Person (var name: String) {
}
1.2 构造函数中定义属性
-
只有在主构造函数中才能定义属性,次构造函数中不能定义属性(即次构造函数中不能使用
var
和val
)。 -
父类中定义的属性,在子类的主构造函数中,不能使用
var
和val
修饰符。 -
主改构造函数中定义的属性,如果没有指定访问修饰,只能在
init
模块中访问,且无法二次赋值;如果指定为val
,可以在类中访问,无法二次赋值;如果指定为var,可以在类外部访问,可以多次赋值。 -
每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托(委托到同一个类的另一个构造函数用 this 关键字即可)
class Student(name: String, var age: Int) : Person(name) {
var tel: String = ""
var addr: String = ""
public constructor(name: String, age: Int, addr: String, tel: String) : this(name, age) {
this.tel = tel
}
}
2. 实战中注意事项
2.1 父类无主构造函数是需要注意的问题
如果一个父类没有定义主构造函数,在定义子类的时候,如果定义了主构造函数,那么子类只能有一个主构造函数,并且只能继承父类的其中一个构造函数。
- 示例
open class Person {
// 父类没有定义构造函数
constructor(name: String) {
}
constructor(name: String, age: Int) {
}
}
class Teacher(name: String) : Person(name) {
// 子类定义了主构造函数,这个构造函数定义是会无法通过编译的
constructor(name: String, age: Int): super(name, age) {
}
}
以上示例中,Person
类没有定义主构造函数,内部定义了两个构造函数,子类 Teacher
定义了主构造函数,那么只能在主构造函数中继承父类的某个构造函数,在类内部无法再定义构造函数,若定义了,编译时将会报错。最佳的做法是,如果父类没有定义主构造函数,在定义子类的时候,子类也不定义主构造函数,在子类内部定义构造函数,并且选择继承父类的构造函数。
- 示例
open class Person {
// 父类没有定义构造函数
constructor(name: String) {
}
constructor(name: String, age: Int) {
}
}
class Teacher : Person {
constructor(name: String) : super(name) {
}
constructor(name: String, age: Int): super(name, age) {
}
}