LastExceed
03/08/2022, 7:29 PMAnimal
and some inheriting classes Dog
Cat
etc, and i want each type of animal to have a lifeExpectancy
. now of course i could just create abstract val lifeExpectancy: Float
inside Animal
and have each child class override that, but that would result in every instance of Dog
holding a copy of the same number, which seems a bit redundant. (yes i know the overhead in this example is insignificant, but the problem is scalable). alternatively i could put the lifeExpectancy in the companion object, but then i can't generically look it up as the companion object can't be accessed generically (or at least i wouldn't know how to do that). i could store a reference to the companion object (or just the data i want to associate with the type in case it's not a primitive) in each instance to keep the overhead insignificantly low, but that would be incredibly ugly
is there any way to do this more elegantly?Casey Brooks
03/08/2022, 7:44 PMabstract class Animal {
abstract val lifeExpectancy: Float
}
class Dog : Animal() {
override val lifeExpectancy: Float get() = LIFE_EXPECTANCY
companion object {
const val LIFE_EXPECTANCY = 9.5f
}
}
Casey Brooks
03/08/2022, 7:54 PMfun main() {
val dog = Dog()
val dogClass = dog::class
val companionForDog = dogClass.companionObjectInstance as AnimalAttributes
val dogLifeExpectancy = companionForDog.lifeExpectancy
}
interface AnimalAttributes {
abstract val lifeExpectancy: Float
}
class Dog {
companion object : AnimalAttributes {
override val lifeExpectancy: Float get() = 9.5f
}
}
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect.full/companion-object-instance.htmlCasey Brooks
03/08/2022, 7:56 PMLastExceed
03/08/2022, 7:58 PMTim Oltjenbruns
03/08/2022, 8:38 PMTim Oltjenbruns
03/08/2022, 8:38 PMTim Oltjenbruns
03/08/2022, 8:39 PMYoussef Shoaib [MOD]
03/09/2022, 10:54 AMimport kotlin.reflect.*
abstract class Animal(lifeExpectancy: Float) {
init {
recordLifeExpectancy(this::class, lifeExpectancy)
}
val lifeExpectancy: Float get() = lifeExpectancyByType[this::class]!!
companion object {
val lifeExpectancyByType: Map<KClass<*>, Float> get() = _lifeExpectancyByType
private val _lifeExpectancyByType: MutableMap<KClass<*>, Float> = mutableMapOf()
fun recordLifeExpectancy(type: KClass<*>, lifeExpectancy: Float) {
_lifeExpectancyByType.getOrPut(type) { lifeExpectancy }
}
}
}
class Dog: Animal(12f)
class Cat: Animal(42f)
fun main() {
println(Dog().lifeExpectancy)
println(Cat().lifeExpectancy)
println(Dog().lifeExpectancy)
println(Cat().lifeExpectancy)
println(Dog().lifeExpectancy)
println(Cat().lifeExpectancy)
println(Animal.lifeExpectancyByType)
}
However, keep in mind that the problem only scales if you have millions of Dog
and Cat
objects, and that each Dog object having the same value in inside of it is fine since if it's an object only a reference ("pointer") to that object will be stored (according to how the JVM works)