Anyone ever needed to make a class with an `init` ...
# getting-started
r
Anyone ever needed to make a class with an
init
block entirely lazy? Example in the thread. (I suspect I'm going to get "smells of a poor design" and that may well be right but my imagination is failing me on how to fix it at the moment...)
Here's the current state of affairs:
Copy code
interface Database {
    fun queryByName(s: String): String
    fun link(thing1: String, thing2: String)
}

class SingletonFoo(
    database: Database
) {
    val lookedUpFromDb1: String = database.queryByName("foo")
    val lookedUpFromDb2: String = database.queryByName("bar")
    
    init {
        database.link(lookedUpFromDb1, lookedUpFromDb2)
    }
}
I need to instantiate
SingletonFoo
on app start - which means that the database needs to be accessible when the app starts, and I don't want to couple the app and the database in that way. I can't just make
lookedUpFromDb1
and
lookedUpFromDb2
lazy because I refer to them in the
init
block.
So I've played with this:
Copy code
interface SingletonFoo {
    val lookedUpFromDb1: String
    val lookedUpFromDb2: String
}

class ActiveSingletonFoo(
    database: Database
) : SingletonFoo {
    override val lookedUpFromDb1: String = database.queryByName("foo")
    override val lookedUpFromDb2: String = database.queryByName("bar")

    init {
        database.link(lookedUpFromDb1, lookedUpFromDb2)
    }
}

class LazySingletonFoo(
    database: Database
) : SingletonFoo {
    private val activeSingletonFoo by lazy { ActiveSingletonFoo(database) }
    override val lookedUpFromDb1: String by lazy { activeSingletonFoo.lookedUpFromDb1 }
    override val lookedUpFromDb2: String by lazy { activeSingletonFoo.lookedUpFromDb2 }
}
My major issue is that rather than 2 props looked up from the DB there are 30+, and repeating each of them 3 times, once in the interface, once in the
Active
and once in the
Lazy
type seems like a lot of boilerplate. But I don't think there's a way to do
class LazySingletonFoo(...) : SingletonFoo by delegate
where the delegate is initialised lazily.
I suspect the answer is I should move the data setup out of the code entirely and into the database migration scripts. Then the
init
block goes away and the properties on
SingletonFoo
can just be lazy without needing an interface. Still, be interesting to know if this is possible in any way.