Reputation: 383
I need to determine the type of a generic parameter in a situation where the type in question can have its own generic types. Below is code that worked until this nesting of generics came up.
inline fun <reified T : Units> Units?.zero(): Measure<T> {
return when (T::class) {
Energy::class -> 0.0 * (joules as T)
Frequency::class -> 0.0 * (hertz as T)
Time::class -> 0.0 * (seconds as T)
Spin::class -> 0.0 * (rpm as T)
Volume::class -> 0.0 * (liters as T)
Temperature::class -> 0.0 * (celsius as T)
UnitsRatio<Energy, Time>::class -> 0.0 * (watts as T) // this does not work
else -> throw RuntimeException()
}
}
Is there a way to get this generic type information about UnitsRatio
?
Background
I'm using Measured, a library to help with managing physical measurement units. Basically, my function is supposed to be a way to obtain a measure with a value of 0 without knowing the exact measurement unit explicitly, as it should be inferred by the compiler. This would enable me to get a sum of measurement values from a collection.
val SUnits: Units? = null
inline fun <T, reified U : Units> Collection<T>.sumOf(selector: (T) -> Measure<U>): Measure<U> {
var sum: Measure<U> = SUnits.zero()
for (element in this) {
sum += selector(element)
}
return sum
}
This makes the usage clean and similar to existing sumOf
variants. For example:
val totalVolume = bodies.sumOf { it.volume }
Upvotes: 1
Views: 53
Reputation: 274480
One way would be to compare against the types, rather than the classes of T
and the unit types.
inline fun <reified T : Units> Units?.zero(): Measure<T> {
return when (typeOf<T>()) {
typeOf<Energy>() -> 0.0 * (joules as T)
typeOf<Frequency>() -> 0.0 * (hertz as T)
typeOf<Time>() -> 0.0 * (seconds as T)
typeOf<Spin>() -> 0.0 * (rpm as T)
typeOf<Volume>() -> 0.0 * (liters as T)
typeOf<Temperature>() -> 0.0 * (celsius as T)
typeOf<UnitsRatio<Energy, Time>>() -> 0.0 * (watts as T)
else -> throw RuntimeException()
}
}
Note that this requires kotlin.reflect
. There might be a better solution specific to the Measured library that you are using, which I am not familiar with.
Upvotes: 1