我们都知道,在Java中按照规范我们应该为每个属性创建setter、getter方法,当然,如果你开心,你也可以不创建,而是把属性声明为public的直接方法。
但是在Kotlin 中,Kotlin标准化了Java中没有固定标准的 getter 和 setter 方法,并且规定调用 Kotlin 类的属性时强制使用 setter 和 getter 方法,不会直接操作类的属性。是不是更安全了呢?
Ok,那么我们示例代码来看下Kotlin中的setter和getter如何定义和使用
package com.anjie.demo
/**
* Created by 安杰 on 2017/10/23. */class Person {
constructor(name: String = "anjie", age: Int = 10) {
println("constructor be called")
this.name = name
this.age = age
}
var name: String = ""
get() {
println("name'get be called value is $field")
return field.toString();
}
set(value) {
println("name'set be called value is $value")
field = value;
};
var age: Int = 0
set(value) {
println("age'set be called value is $value")
field = value
}
get() {
println("age'get be called value is $field")
return field;
}
override fun toString(): String {
return "Person(name='${name}', age=$age)"
}
}
测试代码为:
@Test
fun test2() {
var person1 = Person();
println(person1.toString())
}
结果输出为:
constructor be called
name'set be called value is anjie
age'set be called value is 10
name'get be called value is anjie
age'get be called value is 10
Person(name='anjie', age=10)
看到这里小伙伴可能很惊讶,前面小编还说Kotlin 不允许直接操作类属性,这不是逗我么。大家稍安勿躁。
上面虽然是使用对象.属性的写法,但是 Kotlin 中的“对象.属性”会视情况自动编译为调用 getter 或 setter 方法。也就是kotlin编译后会自动替换为setter和getter
首先介绍一个字段,field,其代表setter或getter生成器对应的属性字段。
可以看到,即使是在构造函数内对属性进行赋值,其也是强制调用setter函数的。
Kotlin有点我不是很理解,就是如果属性设置来setter生成器,你必须对其设置初始值或者在主构造函数对其进行初始化否则就报错不能编译通过,有知道的小伙伴可以给我留言,感激不尽。
当然,我们自定义setter和getter可以做很多事情,如,我对于名字需要做个限制,首字母大写,其他的小写,不管用户输入的是大写还是小写。
代码修改为:
package com.anjie.demo
/**
* Created by 安杰 on 2017/10/23. */class Person {
constructor(name: String = "anjie", age: Int = 10) {
println("constructor be called")
this.name = name
this.age = age
}
var name: String = ""
get() {
println("name'get be called value is $field")
return field.toString();
}
set(value) {
println("name'set be called value is $value")
field = if (value.isEmpty()) "" else value[0].toUpperCase() + value.substring(1);
};
var age: Int = 0
set(value) {
println("age'set be called value is $value")
field = value
}
get() {
println("age'get be called value is $field")
return field;
}
override fun toString(): String {
return "Person(name='${name}', age=$age)"
}
}
结果输出为:
constructor be called
name'set be called value is anjie
age'set be called value is 10
name'get be called value is Anjie
age'get be called value is 10
Person(name='Anjie', age=10)
可以看到,setter的value是 anjie,但最后我们输出的是Anjie,因为我们在setter生成器里面做了格式的转换。
setter、getter使用注意事项
1、需要自定义 setter 或 getter 的属性,不能放在类头里定义,必须在类体内定义,要不然 Kotlin 怎么知道你自定义了哪个属性的 getter 和 setter 呢?所以这里我们把原本在类头里定义的 name 属性挪到了类体内定义,并使用传入的 String 类型参数初始化 name 属性,name 属性被自动推导为 String 类型;
2、getter 是一个没有参数、返回类型与属性类型相同的函数。
完整的写法应该是这样的:
get(): 属性类型 {
//……
}
但是一般 getter 的方法比较短,而且可以自动推导类型,所以如果只有一句的话可以写成“get() = 函数语句”的形式。需要注意一点,不能在 getter 里再调用本属性,因为 Kotlin 代码里所有对属性的访问都会被编译为 getter 方法,这样写就会出现无限迭代和 StackOverFlowError
3、 setter 的参数列表一般有一个与属性类型相同的参数,没有返回值。Kotlin 中一般用 value 表示这个参数,当然也可以用其他关键字;这里的 field 是表示 幕后字段 的关键字,它在使用时相当于 this.name,但是只能用在 setter 方法内
当然,setter和getter能做的事情很多,大家可以在开发过程中结合实际情况灵活运用。