从Kotlin documentation,允许使用自定义设置器:
class Test {
var stringRepresentation: String
get() = field
set(value) {
setDataFromString(value)
}
init {
stringRepresentation = "test"
}
private fun setDataFromString(value: String) { }
}
但如果没有自定义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) { }
}
虽然您可以使用没有自定义设置器的自定义getter,但这里没有问题:
class Test {
var stringRepresentation: String
get() = field
init {
stringRepresentation = "test"
}
private fun setDataFromString(value: String) { }
}
那么为什么你不能在init
块中使用带有属性初始化的自定义setter,为什么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) { }
}
答案 0 :(得分:5)
属性初始值设定项不会调用自定义setter,因为它们的目的是提供默认值。
与Java不同,在Kotlin中,不仅必须在第一次访问之前初始化局部变量,还要对类属性进行初始化。
在Java中,这是有效的。
public class Test {
public String str;
public static void main(String[] args) {
System.out.println(new Test().str);
}
}
在Kotlin,这不是。
class Parent {
var str: String?
}
fun main(args: Array<String>) {
Parent().str
}
因此,自定义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
}
属性stringRepresentation初始化为“a”其类的opon实例化而不调用setter。 然后调用init块并使用setter将值设置为“b”。 然后使用setter “c”。