Last active
September 10, 2024 18:54
-
-
Save beer-avalanche/efb1e8e4c1b94197d21592b1f60a4f31 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inline fun <reified K : Any> summon(): K { | |
val tpe = typeOf<K>() | |
return summon(tpe) as? K | |
?: error("Trait instance must be of type $tpe") | |
} | |
// FIXME: Come up with a way to make it sufficiently weak to prevent | |
// memory leaks due to accumulation of the underlying classes | |
// if class loaders are being closed. | |
private val instances = ConcurrentHashMap<KType, Any>() | |
fun summon(tpe: KType): Any { | |
return instances.computeIfAbsent(tpe) { | |
require(tpe.arguments.size == 1) { | |
"Multi-parameter traits are not supported" | |
} | |
val arg = tpe.arguments[0].type?.classifier as? KClass<*> | |
?: throw IllegalArgumentException("Trait's type parameter must be a class") | |
val companion = arg.companionObjectInstance | |
?: throw IllegalArgumentException("Trait's type parameter must have a companion object") | |
val companionType = arg.companionObject | |
?: throw IllegalArgumentException("Trait's type parameter must have a companion object") | |
val companionProperties = companionType.memberProperties | |
val count = companionProperties.count { it.returnType == tpe } | |
require(count == 1) { | |
"Companion object of the trait's type parameter must have exactly one property of trait's type $tpe" | |
} | |
val field = companionProperties.find { it.returnType == tpe } | |
?: throw IllegalArgumentException("Companion object of the trait's type parameter must have a property of trait's type $tpe") | |
field.getter.call(companion) | |
?: throw IllegalArgumentException("Trait instance must not be null") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment