0

I am new to Kotlin, and I have been experimenting with the language. In Kotlin in Action, it says the following:

The accessor’s visibility by default is the same as the property’s. But you can change this if you need to, by putting a visibility modifier before the get or set keyword.

I have tried to create a property that has a private getter and a public setter, as follows:

class BackingField {
    var aProperty = 1
        private get
        set(value) {
            field = value + 1
        }
}

However, IntelliJ is suggesting me to remove the private modifier before get. Is is possible to have a public property with a private getter and a public setter? If so, what are some common applications of such entity? If not, could we conclude that what is stated in the book is partially wrong?

lmiguelvargasf
  • 63,191
  • 45
  • 217
  • 228

2 Answers2

4

The book is not wrong per se. Because you can actually change the visibility on both the get and set but the set can't be more visible than the get according to this question: Private getter and public setter for a Kotlin property

Ivo
  • 18,659
  • 2
  • 23
  • 35
  • this _the set can't be more visible than the get_ explains everything. Thank you so much! – lmiguelvargasf Sep 22 '20 at 14:19
  • just one clarification, saying that _in Kotlin to have a property with a setter that is more visible than the property_ is the same as saying that _the getter cannot have more visibility than the getter_? If so, can you provide something that backs your answer? (just let me know that before validating your answer, I have already upvoted) – lmiguelvargasf Sep 22 '20 at 14:32
0

Remember that books and IDEs offer recomendations and not good design based on what you do.

The set can't be more visible than the get, as other said, but then remember that properties and backing fields is just an abstraction. You can have no backing field and declare your interface setter and getter methods with the access restrictions you wish for.

Given this use case, it's obvious that you have special requirements. I.e. the data is not just set, but also incremented by 1. So your external interface would probably have another name for it as well.

Having the syntac object.field = x invoke a setter function is suspect as well, cause the syntax implies no function invocation, as in java or C/C++ structs. it can bite you horribly and make you miss the fact that the assignment invokes a setter somewhere in your code - I would consider it bad design.

The feature of properties and getters/setters works mostly if you are working with data objects and pokos (plain old kotlin objects) only. It's very good for those cases, and can save you time, but once you stray off into more complex scenarios, as you are doing, it's weakness will begin to show.

In this case you don't need a setter, because the class will have access to it privately. The getter though, is something you have to define, and perhaps give a more apropriate name, like setAndIncrement.

class BackingField {

    private var aProperty = 1
    fun setAProperty(value:Int) { aProperty=value+1}
    private fun getAProperty():Int { return aProperty }

    fun print() {println(aProperty)}
}

fun main() {
    var f = BackingField()
    f.print()
    f.setAProperty(10)
    f.print()
    println(f.aProperty) // Won't compile
}
GnoSiS
  • 55
  • 8