Reputation: 58
I have the following design that I want to implement in Kotlin:
A non-trivial size of a class hierarchy, sharing a common root (let's call it Base
). All classes of this hierarchy have some parameters, which should be accessible both statically (because they are needed in factory methods) and dynamically (because they are needed from outside code). Plus, since I'll be creating a lot of instances of these classes, I'd like to avoid instantiating a list/set of attributes for each instance.
Here is what I've been able to put together, which works, but feels really ugly.
abstract class Base {
open val params: List<Int> get() = Companion.params
companion object : BaseCompanion()
}
abstract class BaseCompanion {
open val params: List<Int> = emptyList<Int>()
}
class A: Base() {
override val params: List<Int> get() = Companion.params
companion object : BaseCompanion() {
override val params: List<Int> = listOf(1, 3)
}
}
The part that feels really clunky is that every class that inherits from Base
has to:
Is there a better, more Kotlin, way of doing this?
Upvotes: 0
Views: 96
Reputation: 23262
What about doing it the other way around, i.e. pass the list from outside, e.g.:
abstract class Base(val params : List<Int>)
class A(params : List<Int>) : Base(params)
and on the object creation side just hold that "static" list and pass it to your newly created objects:
val staticParams = listOf(1, 3)
val oneOfManyA = A(staticParams)
If you still want that look&feel of instantiating the A
alone without passing the static parameters and/or by holding them in the companion, you can still do so by using the invoke
-operator:
class A(params : List<Int>) : Base(params) {
companion object {
private val staticParams = listOf(1, 3)
operator fun invoke() = A(staticParams)
}
}
now you can just call it as follows and it will instantiate with the static parameters from the companion object:
A()
Note also: as long as you pass the list as is, all lists share the same contents (as you only pass the reference of the original list)... if you would use something like staticParams.toList()
you basically create your own new list that will be passed instead, which is disconnected from the original list.
Depending on what you really want to do an extension property might also fit the purpose (that's not a recommendation, just a way to solve the issue ;-)):
abstract class Base
class A : Base()
val A.params
get() = listOf(1, 3)
// or:
val staticParams = listOf(1, 3)
val A.params
get() = staticParams
That way you can spare companion object
, etc. and have your static list directly attached to A
. This has its own drawbacks but could be a solution as well...
Upvotes: 1