maybe this’ll end up being a dumb question, but wh...
# announcements
s
maybe this’ll end up being a dumb question, but what’s the right approach to take when you have a property you want to assign conditionally based on which constructor you call? the class I’m writing kinda looks like this
Copy code
class Foo(val bar, val baz) {
  val doober = mutableMapOf<String, String>()
  val qux: Set<String>
  constructor(bar, baz, lad) : this(bar, baz) {
    // do things to `doober` using `lad`
    qux = doober.keys.toSet()
  }
}
more specifically,
qux
should be an empty set if the primary constructor is called, and a computed, read-only set if the secondary constructor is called, based on the results of evaluating the parameter unique to it. I tried a separate
init
block declared after the secondary constructor to populate the set using the map, but it looks like the init block gets executed before the logic in the body of the secondary constructor. for kicks, I also tried making
qux
a constructor parameter, but you can’t call the primary constructor from the secondary one using values you compute in the latter
e
"Note that code in initializer blocks effectively becomes part of the primary constructor. Delegation to the primary constructor happens as the first statement of a secondary constructor, so the code in all initializer blocks is executed before the secondary constructor body. Even if the class has no primary constructor, the delegation still happens implicitly, and the initializer blocks are still executed" Quoted from official website.
s
gotcha
e
Copy code
class Foo {
    val doober = mutableMapOf<String, String>()
    val qux: Set<String>

    constructor(bar: String, baz: String) {
        qux = emptySet()
    }

    constructor(bar: String, baz: String, lad: String) {
        // do things to `doober` using `lad`
        qux = doober.keys.toSet()
    }
}
This could work
By making the first
constructor
a non-primary one, they can both initialize
qux
inside the constructor.
s
what if
bar
and
baz
are `private val`s?
e
Copy code
class Foo {
    private val bar: String
    private val baz: String
    val doober = mutableMapOf<String, String>()
    val qux: Set<String>

    constructor(bar: String, baz: String) {
        qux = emptySet()
        this.bar = bar
        this.baz = baz
    }

    constructor(bar: String, baz: String, lad: String) {
        // do things to `doober` using `lad`
        qux = doober.keys.toSet()
        this.bar = bar
        this.baz = baz
    }
}
s
is that not the same code?
e
I pressed enter too early
s
ah gotcha
kind of irritating that you have to assign bar and baz twice though
e
True, but they are in different constructor, so...
Kind of a trade off atm
Maybe you can file a issue on this and see if JetBrain will take into account
s
so after spending way too much time trying to resolve this neatly, I settled on making that last parameter nullable with null as the default parameter, which gets rid of the secondary constructor and uses a
?.let { ... }
to do an assignment
it looks… not amazing, but it’s not the literal worst
I also don’t know if it’s a code smell to have a nullable param that defaults to null
e
definitely not
1