在 Kotlin 中的一个类可以有一个主构造函数以及一个或多个次构造函数。主构造函数是类头的一部分:它跟在类名后面。
主构造函数
class Person constructor(username:String){
}
如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。
class Person (username:String){
}
主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中。
class Person (username:String){
private var name:String
init {
this.name = username
}
}
注意:初始化块中的代码实际上会成为主构造函数的一部分。
次构造函数
类也可以声明前缀有 constructor的次构造函数
如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可。
直接委托给主构造函数
class Person (name:String){
private var name:String
private var age:Int
init {
this.name = name
this.age = 20
}
constructor(name: String,age:Int):this(name){
this.name = name
this.age = age
}
}
间接委托给主构造函数
class Person (name:String){
private var name:String
private var age:Int
private var address :String
init {
this.name = name
this.age = 20
this.address = "hangzhou"
}
constructor(name: String,age:Int):this(name){
this.name = name
this.age = age
this.address = "hangzhou"
}
constructor(name: String,age:Int,address:String):this(name,age){
this.address = address
}
}
创建类的实例
要创建一个类的实例,我们就像普通函数一样调用构造函数:
val person1 = Person("zhangsan")
val person2 = Person("lisi",30)
val person3 =Person("wangwu",40,"shanghai")
注意 Kotlin 并没有 new 关键字。
完整例子
class Person (name:String){
private var name:String
private var age:Int
private var address :String
init {
this.name = name
this.age = 20
this.address = "hangzhou"
}
constructor(name: String,age:Int):this(name){
this.name = name
this.age = age
this.address = "hangzhou"
}
constructor(name: String,age:Int,address:String):this(name,age){
this.address = address
}
fun printInfo(){
println("name:${this.name} , age:${this.age} ,addess:${this.address}")
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
val person1 = Person("zhangsan")
val person2 = Person("lisi",30)
val person3 =Person("wangwu",40,"shanghai")
person1.printInfo()
person2.printInfo()
person3.printInfo()
}
}
System.out: name:zhangsan , age:20 , addess:hangzhou
System.out: name:lisi , age:30 , addess:hangzhou
System.out: name:wangwu , age:40 , addess:shanghai
事实上,声明属性以及从主构造函数初始化属性,Kotlin 有简洁的语法:
class Person(private val name: String, private val age: Int, private val address: String) {
fun printInfo() {
println("name:$name , age:$age ,addess:$address")
}
}
打印下结果
System.out: name:wangwu , age:40 ,addess:shanghai
可以正确的打印出来。说明现在构造方法中的参数中定义的name 、age、 addrress 它们就是是Person类的成员变量或者说是属性。
那么怎么区分是构造方法的参数还是类的属性呢?
我们来比对下不同
构造方法的参数,直接是(参数名:类型名)
class Person (username:String){
}
如果是成员变量(private val 参数名:类型名 )
class Person(private val name: String) {
fun printInfo() {
println("name:$name")
}
}
这里有一个变量var还是常量val,还有一个可选的访问级别private,这个private是可以省略的。
这种简洁的语法在实际开发中式用的比较多。
补充一点小知识:
如果构造函数有注解或可见性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前面:
class Person public @Inject constructor(name: String) { /*……*/ }
如果我们不想外界创建这个Person类的实例,那么可以使用private来修饰。
class Person private constructor(username:String){
}