Kotlin constructors

There’s been something I’ve been struggling with regarding Kotlin constructors.

Kotlin constructors, just like in Java, are invoked after initialization.
That is:

class Foo {
    constructor() {
        println(t) // 3
    } 
    val t: Int = 3 
}

According to the docs, “initializer blocks effectively becomes part of the primary constructor.” However, there’s a pretty big difference. Initializer blocks happen during initialization, not after construction, so you can’t invoke open methods, reference a leaky this, refer to open properties, etc.

The problem I hit is that you can’t declare a val in a secondary constructor (makes sense) but you also can’t write a block for the primary constructor.

class Foo {
    
    // val on secondary constructor parameter not allowed
    constructor(val f: Int) { 
        println(f)
        println(t)
    }
    val t: Int = 3
}

In that example it is confusing that the constructor is considered secondary, especially given that you can’t construct Foo as Foo()

To give a real use case, let’s take an example from the kotlin constructor documentation:

class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf()
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

This example breaks down if you wanted parent to be a required val.

Often you can work around the issues I’m talking about by using a private primary constructor and public secondary, but then you hit a problem with overload ambiguity.

Example:

class Foo private constructor(val f: Int) {

	// Overload resolution ambiguity
	constructor(f: Int) : this(f) {
		println(f)
		println(t)
	}

	val t: Int = 3
}

A proposed solution, which I could have sworn existed in the early days of Kotlin…
I would like the ability to do the following:

open class Foo {
    
    primary constructor(val f: Int) : Bar() { 
        println(f)
        println(t) // Possibly overridden value
    }

    open val t: Int

    init {
        t = 3
    }
}