使用Kotlin属性访问语法设置Java字段是否安全?

Bel*_*bub 5 java kotlin

这是一个假设的问题。情况如下:我正在从Kotlin文件中调用Java类的setter来更改私有字段的值x

javaFoo.setX(420)
Run Code Online (Sandbox Code Playgroud)

IDE建议将其更改为

javaFoo.x = 420
Run Code Online (Sandbox Code Playgroud)

它正常工作。

现在假设二传手有它的一些复杂的功能里面,后来的xJava类中的字段将变为public代替private。不会有编译错误,但Kotlin调用将更改x跳过setter中发生的其他操作的值 ,并且可能会被忽略而导致逻辑错误。因此,我想知道:使用Kotlin属性访问语法设置Java字段是否安全?

Mar*_*nik 3

您对语言语义的分析是正确的。您描述的目标类的更改确实会更改 Kotlin 属性访问语法的语义。然而,这一事实并不是回答您的问题时要考虑的唯一事实,该问题询问使用该语法是否安全

当讨论没有任何现实生活限制的假设场景时,几乎一切皆有可能,并且在这种观点下没有语言构造是“安全的”。如果有一天,Kotlin 团队决定将 的语义更改x++为“x平方回报,不改变x”怎么办?从理论上讲,这是可能的。但这有可能吗?

将相同的常识逻辑应用于您的问题,类的维护者决定破坏迄今为止隐藏在具有自定义逻辑的设置器后面的字段的封装的情况是极不可能的。事实上,如果您对所有 Java 库项目进行历史分析,您可能不会发现曾经发生过这种情况。


也就是说,您的假设场景可能会被视为分散了对快捷语法实际问题的注意力。使用它来调用具有自定义逻辑的 setter 可能会很尴尬且具有误导性,因为它打破了我们的直觉。

在 Android 上,这样的一个例子是ImageView.get/setImageMatrix. 你可以写

imageMatrix.rotate = 30
Run Code Online (Sandbox Code Playgroud)

并期望这会产生效果,但实际上,您编写的代码已损坏。你实际上应该写

val tmpMatrix = Matrix()
tmpMatrix.set(imageMatrix)
tmpMatrix.rotate = 30
imageMatrix = tmpMatrix
Run Code Online (Sandbox Code Playgroud)

根据我们 Java 的直觉,实际上这个版本看起来很糟糕,看似毫无目的地浪费了对象分配。但是如果您阅读了 的契约setImageMatrix,您会意识到它所做的不仅仅是将对象分配给字段,它实际上将转换应用于图像视图。类似地,getter 的契约不允许改变返回的对象。


我还没有看到关于 Kotlin 的这一功能的太多争论,但我认为对于从 Java 迁移的人们来说,它是一个潜在的错误来源。正确的方法是重新训练你的直觉,让自己意识到 Kotlin 中的任何属性访问可能意味着的意义远比表面上看到的要大得多。