简体   繁体   English

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

[英]Is it safe to use Kotlin property access syntax to set a Java field

This is a hypothetical question. 这是一个假设的问题。 The situation is the following: I am calling a setter of a Java class from a Kotlin file to change the value of the private field x 情况如下:我从Kotlin文件调用Java类的setter来更改私有字段x的值

javaFoo.setX(420)

The IDE suggests to change it to IDE建议将其更改为

javaFoo.x = 420

It works normally. 它正常工作。

Now suppose the setter has some complicated functionality inside of it and later on the x field in the Java class is changed to public instead of private . 现在假设setter里面有一些复杂的功能,后来在Java类中的x字段被改为public而不是private There will be no compile error but the Kotlin call will change the value of x skipping the other stuff that happens in the setter, and it can go unnoticed causing logical errors. 没有编译错误,但Kotlin调用将改变x跳过setter中发生的其他东西的值,并且它可能会被忽视而导致逻辑错误。 Therefore I am wondering: Is it safe to use Kotlin property access syntax to set a java field? 因此我想知道: 使用Kotlin属性访问语法来设置java字段是否安全?

Your analysis of the language semantics is correct. 您对语言语义的分析是正确的。 The change on the target class you describe would indeed change the semantics of Kotlin's property access syntax. 您描述的目标类的更改确实会改变Kotlin的属性访问语法的语义。 However, that fact is not the only one to consider when answering your question, which asks whether using that syntax is safe . 但是,在回答您的问题时,这个事实并不是唯一要考虑的问题,因为问题是否使用该语法是安全的

When discussing hypothetical scenarios without any real-life constraints, pretty much anything is possible and no language construct is "safe" under that view. 在讨论没有任何实际约束的假设情景时,几乎任何事情都是可能的,并且在该视图下没有语言结构是“安全的”。 What if, one day, the Kotlin team decided to change the semantics of x++ to mean "return x squared, not changing x "? 如果有一天,Kotlin团队决定将x++的语义改为“返回x平方,而不是改变x ”,该怎么办? Theoretically, that's possible. 从理论上讲,这是可能的。 Is it likely, though? 不过可能吗?

Applying the same common-sense logic to your question, the scenario where the maintainer of a class decides to break the encapsulation of a field that has so far been hidden behind a setter with custom logic is extremely unlikely. 在您的问题中应用相同的常识逻辑,类的维护者决定打破迄今为止隐藏在具有自定义逻辑的setter后面的字段的封装的情况极不可能。 In fact, if you make a historical analysis of all the Java library projects, you probably won't find a single instance of this having ever happened. 实际上,如果对所有Java库项目进行历史分析,您可能找不到发生过这种情况的单个实例。


That said, your hypothetical scenario could be seen as a distraction from an actual problem with the shortcut syntax. 也就是说,您的假设场景可能被视为分散了快捷语法的实际问题。 It can be awkward and misleading to use it to call a setter with custom logic because it breaks our intuition. 使用它来调用具有自定义逻辑的setter可能会很尴尬和误导,因为它打破了我们的直觉。

On Android, one such example is ImageView.get/setImageMatrix . 在Android上,一个这样的例子是ImageView.get/setImageMatrix You can write 你可以写

imageMatrix.rotate = 30

and expect that to have an effect, but actually, the code you wrote is broken. 并期望有效,但实际上,你写的代码是破碎的。 You should actually have written 你应该写的

val tmpMatrix = Matrix()
tmpMatrix.set(imageMatrix)
tmpMatrix.rotate = 30
imageMatrix = tmpMatrix

By our Java intuition, it is actually this version that looks broken, wasting an object allocation for seemingly no purpose. 根据我们的Java直觉,实际上这个版本看起来很破旧,浪费了一个似乎没有目的的对象分配。 But if you read the contract of setImageMatrix , you'll realize it does quite a bit more than just assign your object to a field, it actually applies the transformation to the image view. 但是如果你阅读了setImageMatrix的契约,你会发现它比仅仅将对象分配给一个字段要多得多,它实际上将转换应用于图像视图。 Similarly, the contract of the getter disallows mutating the returned object. 类似地,getter的契约不允许改变返回的对象。


I haven't seen much argument over this feature of Kotlin, but I see it as a potential source of bugs for folks migrating from Java. 我没有看到很多关于Kotlin这个功能的争论,但我认为它是从Java迁移的人们的潜在漏洞来源。 The way to go is to re-train your intuition, sensitizing yourself to the fact that any property access in Kotlin may mean a lot more than meets the eye. 要走的路是重新训练你的直觉,让自己认识到Kotlin的任何财产访问可能意味着远远超过眼睛。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM