Hi all, I wanted to know what is the meaning of th...
# getting-started
b
Hi all, I wanted to know what is the meaning of the statement "If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s)." in simple English.
k
If your class has a primary constructor, then any secondary constructors that you add need to eventually call it
5
They can either do so by delegating to it directly, or through another secondary constructor that delegates to it. But eventually it needs to reach the primary constructor
5
b
You mean the compiler right?
k
It's a compilation requirement, yeah
b
Copy code
class Playground(val name: String, val count: Int) {

    // Call primary constructor directly
    constructor(name: String) : this(name, 1) {
        println("Using default count")
    }

    // Call primary constructor indirectly
    // through another secondary constructor
    constructor() : this("N/A", 2) {
        println("Using default name")
    }
}
I was playing around with this, and I came across this situation when i tried calling the primary constructor directly from both of my secondary constructors, and the result was "Using default name", why didn't the first constructor run?
a
I’m confused as it does what I’d expect:
Copy code
val a = Playground() // prints "Using default name"
val b = Playground("Single Parameter Constructor") // prints "Using default count"
val c = Playground("Calls Primary Constructor", 23) // prints nothing as it's the primary
I’m not sure what you mean “why didn’t the first
constructor
run”? It runs if you pass a single string parameter. You can have the “second”
constructor
call the “first”, which in turn calls the primary:
Copy code
class Playground(val name: String, val count: Int) {

  // Call primary constructor directly
  constructor(name: String) : this(name, 1) {
    println("Using default count")
  }

  // Call primary constructor indirectly
  // through another secondary constructor
  constructor() : this("N/A") { // calls the "first"
    println("Using default name")
  }
}
Side note: I’m not a fan of overloading constructors. I try to look for ways to default the parameter values in the primary whenever possible. This example can be reduced to:
Copy code
class Playground(val name: String = "N/A", val count: Int = 1)
@Ruckus My design approach has changed much from switching to Kotlin years ago. Defaulting args, builders, factory methods/functions or implementing
invoke
on a companion object while keeping the constructors private. I often forget how to write a constructor as I just avoid the spaghetti code of the combinatorics of creating instances via constructor args and having to figure out the best way to provide proper hidden defaults. Complex constructors are a code smell (to me). I also avoid subclasses like the plague. That’s a different topic altogether. 😄