Zoltan Demant
10/10/2023, 6:09 AMinterface Dispatcher<T : Request<R>, R> {
val type: KClass<T>
suspend fun dispatch(
request: T,
): R
}
Zoltan Demant
10/10/2023, 6:15 AMList<Dispatcher<*,*>>
which Id like to turn into Map<KClass<out Request<*>>,Dispatcher<*,*>>
. I can successfully do this with the type property, but it would be nice to not have to declare type over and over and over again (194 times, and counting).ephemient
10/10/2023, 6:19 AMephemient
10/10/2023, 6:20 AMimport kotlin.reflect.*
interface Dispatcher<T>
class FooDispatcher : Dispatcher<Int>
class BarDispatcher : Dispatcher<String>
listOf(FooDispatcher(), BarDispatcher()).associateBy {
it::class.supertypes
.first { it.classifier == Dispatcher::class }
.arguments.single().type!!.classifier as KClass<*>
} == mapOf(Int::class to FooDispatcher(), String::class to BarDispatcher())
ephemient
10/10/2023, 6:22 AMDispatcher<some concrete class>
or r8 has stripped out metadata)Zoltan Demant
10/10/2023, 6:26 AM@JvmInline
value class GetAccount(
val id: Id,
) : Request<AccountView>
class GetAccountDispatcher(
...
) : Dispatcher<GetAccount, AccountView>
Will try your solution in a little bit 🙂ephemient
10/10/2023, 6:33 AMabstract class AbstractDispatcher<T, R> : Dispatcher<T, R>
class ConcreteDispatcher : AbstractDispatcher<Foo, Bar>()
then my snippet will fail. it's possible to handle, but annoyingephemient
10/10/2023, 6:34 AMclass GenericDispatcher<T, R> : Dispatcher<T, R>
GenericDispatcher(...)
then that will fail since generics are erased at runtimeephemient
10/10/2023, 6:36 AMDispatcher
sealed, and even adding a test that checks that all of Dispatcher::class.sealedSubclasses
are okZoltan Demant
10/10/2023, 6:45 AMephemient
10/10/2023, 6:49 AMephemient
10/10/2023, 6:51 AMval Dispatcher<T>.type: KClass<T> @Suppress("UNCHECKED") get() = when (this) {
is FooDispatcher -> Foo::class
// etc.
} as KClass<T>
at compile-timeZoltan Demant
10/10/2023, 7:03 AMKotlin reflection takes a little time to initialize, and Java reflection (which Kotlin reflect uses underneath) on Dalvik has historically been slower than desktop JVMsAh yes, I did not consider this. Maybe an annotation processor is preferrable, Ill check how long it might take to implement that 😄 Ultimately trying to do this to save time, and Im starting to feel pulled in to creating something much larger than the initial problem 😅
ephemient
10/10/2023, 7:12 AMabstract class Dispatcher<T : Request<R>, R>(val type: KClass<T>) {
inline <reified T : Request<R>, R> constructor(): this(type = T::class)
}
class FooDispatcher : Dispatcher<FooRequest, Foo>()
will be possible. until then, if you're under time constraints, I'd just leave the val type: KClass<T>
as-is. it's not broken and doesn't need additional testingZoltan Demant
10/10/2023, 7:40 AM