从Kotlin文档中,允许使用自定义setter:
class Test {
var stringRepresentation: String
get() = field
set(value) {
setDataFromString(value)
}
init {
stringRepresentation = "test"
}
private fun setDataFromString(value: String) { }
}
Run Code Online (Sandbox Code Playgroud)
但是,如果没有自定义getter(并从init块中初始化),则无法拥有自定义setter :
class Test {
// Compilation error: "Property must be initialized"
var stringRepresentation: String
set(value) {
setDataFromString(value)
}
init {
stringRepresentation = "test"
}
private fun setDataFromString(value: String) { }
}
Run Code Online (Sandbox Code Playgroud)
虽然你可以有一个没有自定义setter的自定义getter,但这里没问题:
class Test {
var stringRepresentation: String
get() = field
init {
stringRepresentation = "test"
}
private fun setDataFromString(value: String) { }
}
Run Code Online (Sandbox Code Playgroud)
那么为什么你不能使用自定义setter和从init块中初始化的属性,为什么init块在属性初始化程序直接分配时调用自定义setter,绕过自定义setter?
class Test {
var stringRepresentation: String = "" // Does not call custom setter
set(value) {
setDataFromString(value)
}
init {
stringRepresentation = "test" // Calls custom setter
}
private fun setDataFromString(value: String) { }
}
Run Code Online (Sandbox Code Playgroud)
属性初始值设定项不会调用自定义setter,因为它们的目的是提供默认值.
与Java不同,在Kotlin中,不仅必须在第一次访问之前初始化局部变量,还必须初始化类属性.
在Java中,这是有效的.
public class Test {
public String str;
public static void main(String[] args) {
System.out.println(new Test().str);
}
}
Run Code Online (Sandbox Code Playgroud)
在Kotlin,这不是.
class Parent {
var str: String?
}
fun main(args: Array<String>) {
Parent().str
}
Run Code Online (Sandbox Code Playgroud)
因此,自定义setter需要通过属性初始值设定项或构造函数初始化其属性.看一下下面的例子.
class Test {
var stringRepresentation: String = "a" // Default value. Does not call custom setter
get() = field
set(value) {
println("Setting stringRepresentation property to %s. Current value is %s.".format(value, field))
field = setDataFromString(value)
}
init {
this.stringRepresentation = "b" // Calls custom setter
}
private fun setDataFromString(value: String): String {
println("Setting stringRepresentation property to %s.".format(value))
return value
}
}
fun main(args: Array<String>) {
Test().stringRepresentation = "c" // Calls custom setter
}
Run Code Online (Sandbox Code Playgroud)
属性stringRepresentation初始化为其类的"a" opon实例,而不调用setter.然后调用init块并使用setter 将值设置为"b".然后使用setter 来"c".