5
votes

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

javaFoo.setX(420)

The IDE suggests to change it to

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. 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. Therefore I am wondering: Is it safe to use Kotlin property access syntax to set a java field?

1
@Belzebub The IDE suggests to change it to... can you provide an example for me to reproduce it?user8959091
I use android studio, just create a java class with a private field and a getter and setter, then call the setter from a kotlin fileBelzebub
It's extremely unlikely that a Java library will change a field from private to public when there's also a setter for this field. Moreover, the behavior of the Kotlin code will only change if you recompile it.yole
And even more unlikely if "the setter has some complicated functionality inside of it".Alexey Romanov

1 Answers

2
votes

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. 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"? 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. 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.


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.

On Android, one such example is 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. 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. Similarly, the contract of the getter disallows mutating the returned object.


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. 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.