Kotlin sublass constructors do not inherit default parameter values

I’ve come across what appears to be a short-coming of the Kotlin language where it concerns default parameters in constructors. Perhaps there’s something in the documentation that I missed? It appears that default parameters for constructors are not inherited, which is strange, because default parameters for other functions are inherited.

open class ClassA {
    constructor(
        id: String,
        name: String = "",
    )
}
class ClassB : ClassA {
    constructor(
        id: String,
        name: String,   // <-- default value must be explicit, cannot inherit or pass through to super
    ) : super(
        id,
        name,   // <-- has default value
    )
}
class ClassC : ClassA {
    constructor( // <-- cannot be instantiated with two constructor arguments
        id: String
    ) : super(
        id      // <-- legal call to super constructor, but omits second parameter
    )
}
fun createClass() {
    val a: ClassA =
        ClassA("123")
    val b: ClassB =
        ClassB("123")   // <-- illegal syntax, not enough arguments
    val c: ClassC =
        ClassC("123", "Jerry")  // <-- illegal syntax, too many arguments
}

However, in other functions, default parameters are inherited, like so:

open class Parent {
    open fun printSomething(argument: String = "default") {} //default value is defined
}
class Child : Parent() {
    override fun printSomething(argument: String){ // no default val specified
        println(argument)
    }
}
fun printTest() {
    Child().printSomething() // compiles successfully, and prints "default"
}

Why is it that only constructors have this limitation of unavailability of default parameters through inheritance? This seems like a design flaw. The default value for a constructor should ‘trickle down’ to it’s subclasses the same as it does for other functions. Otherwise refactoring will become exhausting. Say I have a Parent class with 16 Child classes; I will have to change the default parameters for each constructor in all 17 classes because I’m forced to explicitly declare these values in each subclass. I’ve seen in some examples that we can declare a function which returns the default value, so each constructor (parent and child classes) would call this function to retrieve the default value, but for long parameter lists, this adds unnecessary and undesirable boilerplate code.

Why are the default parameter values not inherited by subclasses?

Constructor are simply not inherited, and they very likely shouldn’t be, ever. A constructor is inherit to the implementation of this one specific class.
Note that in your example, the “trickling down” happened because of override. If Kotlin had inheriting constructors, then sure this would happen.
Inheriting constructors is likely never going to happen because then open classes can dictate that their constructor is inherited, and hence subclasses can’t declare a more complicated constructor. That’s bad because, again, a subclass might want some required parameters.

1 Like