How to not override superclass default values?


#1

Hi

I’m currently taking a Kotlin for Java developers course on Udemy and asked the following question there.

I’d thought I’d ask it here as well to see if maybe some of you know if there is a way to do what I’m asking for.

Best regards
// Björn

Hi,

In the 3rd challenge (lecture 51) when modifying the KotlinBike gear parameter to be optional, Kotlin seems to force us to either specify it as optional (with an explicit value) in the subclasses as well

 open class KotlinBicycle(var cadence: Int, var speed: Int, var gear: Int = 10)
  
 class KotlinMountainBike(var seatHeight: Int, cadence: Int, speed: Int, gear: Int = 10) : 
     KotlinBicycle(cadence = cadence, speed = speed, gear = gear)

or to not provide the option for the user of our subclass to provide a gear parameter at all

open class KotlinBicycle(var cadence: Int, var speed: Int, var gear: Int = 10)

class KotlinMountainBike(var seatHeight: Int, cadence: Int, speed: Int) :
KotlinBicycle(cadence = cadence, speed = speed)

I can think of plenty of situations where I would be perfectly fine with a sensible superclass default value while still wanting to provide the option for the user of my subclass to specify the parameter.

Having to explicitly copy the superclass default value for a parameter is really not a good solution for this situation since it forces me to actually look it up in the code of the superclass (if that is available) and secondly to change it in multiple places should I want to change the default at a later time.

Is there some mechanism in Kotlin that lets me rely on the superclass default while still providing the user an option to change it at construction time of the subclass (or rather without sacrificing immutability of the value in case of a val property)?. Secondary constructors doesn’t seem to solve this problem since I still need to call the primary constructor as a part of those.

Best regards

// Björn


#2

I found the answer to what I was looking for (it might seem obvious in retrospect, but I was still struggling with it) so I’ll post it here as well.

I did some more experimenting and found the answer. The trick was to skip the subclass primary constructor and to specify multiple secondary constructors (corresponding to what I would have to do in Java).

This is what I did.

class KotlinMountainBike : KotlinBicycle {
 
    var seatHeight: Int
 
    constructor(seatHeight: Int, cadence: Int, speed: Int, gear: Int) : super(cadence, speed, gear) {
        this.seatHeight = seatHeight
    }
 
    constructor(seatHeight: Int, cadence: Int, speed: Int) : super(cadence, speed) {
        this.seatHeight = seatHeight
    }
}

#3

The solution is not having primary constructors for the subclass at all. You have two “secondary” constructors only that forward with or without the parent default value. They aren’t really secondary as there is no primary. Rather it mimics regular Java constructor overloading.