Kotlin-有用性;计算的;var属性?
我注意到,当我有一个Kotlin-有用性;计算的;var属性?,kotlin,Kotlin,我注意到,当我有一个var属性和一个自定义get,它不使用字段标识符时,仍然会生成一个支持字段。我检查了字节码,文档也这么说: 如果属性使用 至少一个访问器的默认实现,或者 自定义访问器通过字段标识符引用它。 (重点是我的) 考虑这样一个类。由于它是一个var属性,因此将生成一个默认的set(以及一个支持字段): class Banana { var ripeness = 1 var color: String = "green" get() = when {
var
属性和一个自定义get
,它不使用字段
标识符时,仍然会生成一个支持字段。我检查了字节码,文档也这么说:
如果属性使用
至少一个访问器的默认实现,或者
自定义访问器通过字段标识符引用它。(重点是我的) 考虑这样一个类。由于它是一个
var
属性,因此将生成一个默认的set
(以及一个支持字段):
class Banana {
var ripeness = 1
var color: String = "green"
get() = when {
ripeness > 80 -> "brown"
ripeness > 50 -> "yellow"
else -> "green"
}
}
val b = Banana()
b.color = "blue"
println(b.color)
但是,println
将始终打印“绿色”,无论我将颜色设置为什么。无论如何,支持字段都将设置为“蓝色”。
由于在访问器方法之外(或通过反射)无法访问它,我真的想不出这样做的原因。
我是不是遗漏了什么?可能是一个用例或另一种访问支持字段的方式?或者它只是一个bug(或者IntelliJ中缺少警告)?带有未使用备份字段的“计算的”var
属性应该是“计算的”val
属性
如果您不打算在示例中使用backing字段,那么Banana.color
不应该是var
而是val
。e、 g:
class Banana {
var ripeness = 1
val color: String
get() = when {
ripeness > 80 -> "brown"
ripeness > 50 -> "yellow"
else -> "green"
}
}
另一方面,如果您确实希望在某些情况下使“computed”属性可重写,那么您需要实际使用backing字段。e、 g:
class Banana {
var ripeness = 1
var color: String = "green"
get() = when {
ripeness > 80 -> "brown"
ripeness > 50 -> "yellow"
else -> field
}
}
当心瓦尔。。。get(),其行为可能会非常令人惊讶:
class Val {
val millis: Long = System.currentTimeMillis()
}
class ValGet {
val millis: Long
get() = System.currentTimeMillis()
}
val v = Val()
val g = ValGet()
for(i in 0..4) {
println("val:" + v.millis + " valget:"+g.millis)
Thread.sleep(7)
}
如果一个val x:Int
在引用两次时不能被依赖为相同,那么val
有什么用处?显然,如果父级足够开放,它甚至可以用于覆盖,抽象val looksQuiteLikeImmutable:Int
可能会产生误导。感觉又像是超级棒了。。。(至少这是我在1.4.21中观察到的)用例是您可能希望在自定义getter中使用backing字段。不这样做会使支持字段变得无用。我认为这应该给编译器一个警告。@marstran是的,我同意这个警告。这是一个边缘案例,但您可以很快遇到它,所以我认为可能还有更多。是的,我知道我应该声明它val
。我只是认为这是一个陷阱,特别是初学者可能很容易遇到,因此我认为可能有一个很好的理由允许它。嗯,millis
对象的属性,val
表示对象的用户不能更改它。但是用户不应该期望它不会改变。然而,在这种特殊情况下,函数可能比属性更有意义,因为系统毫不是任何对象的属性。。。除了系统……这可能会产生误导,因为对于新手来说,val-somthing:Int
显然不像描述函数返回类型。get()
实际上成为了类型的一部分,但惯例将其放在单独的一行上,并且在第一行上没有任何表示类型尚未完全指定的指示。在我看来,这绝对是一个“小心”的陷阱。像IntelliJ这样的工具(他们应该知道关于kotlin的一两件事)在使用站点上呈现的都是相同的(包括Javafinal long某物的实际等价物;
,默认构造函数中定义的val)。