Home > Software engineering >  Kotlin automatically generates Getters and Setters, but WHY?
Kotlin automatically generates Getters and Setters, but WHY?

Time:10-10

I'm new to learning Kotlin, and have just covered the fact that Getters and Setters for every object property are automatically generated behind the scenes, like Lombok is built directly into the language (great as far as I'm concerned!), but now I'm left with the question of why does it even bother?

I know you can override the defaults to change how they act, but why is this not just that case of them being created when you need to do something more complex that just getting or setting the value, but just accessing the property normally otherwise?

Having used Java a lot previousky, I understand there are arguments for and against the use of Getters and Setters. Many say they're actually pointless and a bad approach to OOP, others would say they're best practice and should be used everywhere. The way many modern frameworks and libraries are written makes them necessary in lots of cases. This argument spans many different languages, but this question isn't really about the theoretical reasons for them in OOP as a whole, I'm looking for insight specifically into why they're used in Kotlin by default, when to my (perhaps naive) eyes it looks like they needn't be.

What would be the practical difference if Kotlin didn't generate standard Getters and Setters and dot notation simply accessed the property directly? Syntactically, as far as I can see, it produces the same result, just with extra steps.

CodePudding user response:

What would be the practical difference if Kotlin didn't generate standard Getters and Setters and dot notation simply accessed the property directly?

So what you are suggesting is, for properties without custom getters/setters,

// Accessing x would access the field backing the property directly
// no getter or setter
var x: Int = 1

And for properties with custom getters/setters,

// both a field and a setter is generated for y
var y: Int = 1
    set(newValue) { 
        field = newValue.also { println("y is being set!") } 
    }

// only a getter is generated for z, no field
val z get() = 1

The appropriated getter or setter or both will be generated depending on which ones you wrote.

Well, this would be problematic in a few ways. Here's what I could think of.

Firstly, all of this "when (not) to generate a getter/setter" logic is going to make the compiler more complicated. Why do that, when you can just simply generate a getter and setter, unconditionally, for every property?

Secondly, for Java code interacting with the Kotlin code, they would only have a field to work with, in the case of x, and public fields in Java doesn't look idiomatic at all... Let's say at some point you add a getter to x so that it's computed from something else, rather than backed by a field, then all the Java code would break, because there is no longer a field. I'm not sure whether this is also true on Kotlin/JS.

Thirdly, accessing the values of properties through reflection would be more annoying. You would need to check if it has a getter. If it does, call it. Otherwise, access the backing field instead. They could provide you with a helper property on KProperty that does on this for you, but still, that's a lot more complicated than simply calling the getter and be done with it.

Do note that just for JVM, there is the annotation @JvmField that you can use to make a property not have getters and setters, as far as the JVM is concerned. Kotlin's reflection API will still find a getter and setter though.

CodePudding user response:

The two main arguments against getters and setters:

  1. Verbose. But they aren't verbose in Kotlin.

  2. Performance overhead. But it's not a concern with modern JVM's.

It's much safer for future-proofing to use getters and setters from the original design of a class, even if they are just passing through reads and writes to a field. It leaves open the possibility of adding side effects if you need to later. Forcing the use of properties prevents the possibility of you designing yourself into a corner.

Also, a language is easier to read and write when there are fewer ways of doing the same task. You never have to remember if the property you want to access on a class uses a getter function syntax versus standard property syntax.

  • Related