Private set(value) requires initilization before init{ }

I am trying to understand why in a class this is possible:

var relevantPoint: Point 
    private set  // this works

init {
    if (points.size < 3) // doing validation 
        throw IllegalArgumentException("Incomplete Data!")

       relevantPoint = points.first() // here the point gets initialized
}

but not this:

var relevantPoint: Point 
    private set(value) { // Why can't I do this? -> "Property must be initialized - Error"
            field = value // actually redundant unless more functionality applies
    }

init {
    if (points.size < 3) // doing validation 
        throw IllegalArgumentException("Incomplete Data!")

       relevantPoint = points.first() // here the point gets initialized
}

In both cases the init { } will initialize the var.
Is this possibly a wrong check in the compiler?

I think the issue might be that your setter can be arbitrarily complex, and so it could even access the field before setting it, which requires that your relevantPoint field be already set.

2 Likes

Another issue is that a custom setter isn’t forced to write to the field. As such, the compiler can’t guarantee that there will be a value in the property post-init.

2 Likes

You can write this:

    var relevantPoint: Point =
        run { // or `let`
            require(points.size >= 3) { "Incomplete data" }
            points.first()
        }
        private set(value) {
            field = value
            println("setter called")
        }
2 Likes

A key observation here is that with an implementation for the setter, the init block will call that setter, where the initialization will not. This means that inside the setter, the field variable will also be unset (and setters can read the field if needed).

2 Likes