Josh Feinberg
01/10/2025, 3:03 AMJosh Feinberg
01/10/2025, 3:04 AMfun main() {
val function = ::myFunction
val parameters = function.parameters
function.callBy(mapOf(parameters[0] to 1)) // a: 1; b: default value
val myClass = MyClass()
val classFunction = MyClass::myClassFunction
val classFunctionParameters = classFunction.parameters
classFunction.callBy(mapOf(classFunctionParameters[0] to myClass, classFunctionParameters[1] to 2)) // a: 2; b: default value
val myInterfaceImpl = MyInterfaceImpl()
val interfaceFunction = MyInterface::myInterfaceFunction
val interfaceFunctionParameters = interfaceFunction.parameters
interfaceFunction.callBy(mapOf(interfaceFunctionParameters[0] to myInterfaceImpl, interfaceFunctionParameters[1] to 2))
// throws IllegalArgumentException: No argument provided for a required parameter: instance parameter of fun MyInterfaceImpl.myInterfaceFunction(<http://kotlin.Int|kotlin.Int>, kotlin.String): kotlin.Unit
}
fun myFunction(a: Int, b: String = "default value") {
println("a: $a; b: $b")
}
class MyClass {
fun myClassFunction(a: Int, b: String = "default value") {
println("a: $a; b: $b")
}
}
interface MyInterface {
fun myInterfaceFunction(a: Int, b: String = "default value")
}
class MyInterfaceImpl : MyInterface {
override fun myInterfaceFunction(a: Int, b: String) {
println("a: $a; b: $b")
}
}
Josh Feinberg
01/10/2025, 3:05 AMephemient
01/10/2025, 3:16 AMJosh Feinberg
01/10/2025, 3:17 AMephemient
01/10/2025, 3:32 AMval myInterfaceImpl = MyInterfaceImpl()
val interfaceDefaults = Class.forName("${MyInterface::class.java.name}\$DefaultImpls")
val interfaceDefaultFunction = interfaceDefaults.getDeclaredMethod(
"${MyInterface::myInterfaceFunction.name}\$default",
MyInterface::class.java,
Int::class.java,
String::class.java,
Int::class.java, // mask
Object::class.java, // marker
)
interfaceDefaultFunction.invoke(
null, // static
myInterfaceImpl,
2,
null, // default
3, // parameters 0 and 1 are given
null, // marker
)
ephemient
01/10/2025, 3:34 AM$default
wrapper that fills in the defaults. for a class this gets implemented in the same class, but as Java interfaces (at the time) didn't support final or static methods, Kotlin puts it in a different classJosh Feinberg
01/10/2025, 3:35 AMephemient
01/10/2025, 3:53 AMval myInterfaceImpl = MyInterfaceImpl()
val interfaceFunction = MyInterface::myInterfaceFunction
val interfaceFunctionParameters = interfaceFunction.parameters
val interfaceFunctionParametersMap = mapOf(
interfaceFunctionParameters[0] to myInterfaceImpl,
interfaceFunctionParameters[1] to 2,
)
val interfaceDefaults = Class.forName("${MyInterface::class.java.name}\$DefaultImpls")
val interfaceDefaultFunction = interfaceDefaults.getDeclaredMethod(
"${MyInterface::myInterfaceFunction.name}\$default",
*interfaceFunctionParameters.map { (it.type.classifier as KClass<*>).java }.toTypedArray(),
Int::class.java, // need more ints if you have more than 32 parameters,
Object::class.java // marker
)
interfaceDefaultFunction.invoke(
null, // static
*interfaceFunctionParameters.map {
if (it in interfaceFunctionParametersMap) {
interfaceFunctionParametersMap[it]
} else {
when (it.type.classifier) {
Boolean::class -> false
Byte::class -> 0.toByte()
Short::class -> 0.toShort()
Int::class -> 0
Long::class -> 0L
Float::class -> 0f
Double::class -> 0.0
Char::class -> '\u0000'
else -> null
}
}
}.toTypedArray(),
interfaceFunctionParameters.withIndex().fold(0) { acc, (i, param) ->
acc or if (param in interfaceFunctionParametersMap) 1 shl i else 0
}, // mask
null, // marker
)
Josh Feinberg
01/10/2025, 4:17 AMval interfaceDefaultFunction = interfaceDefaults.getDeclaredMethod(
"${MyInterface::myInterfaceFunction.name}\$default",
*interfaceFunctionParameters.map { (it.type.classifier as KClass<*>).java }.toTypedArray(),
Continuation::class.java,
Int::class.java, // need more ints if you have more than 32 parameters,
Object::class.java // marker
)
then call it by wrapping it
val x = suspendCoroutine<Any> { continuation ->
interfaceDefaultFunction.invoke(
null, // static
*interfaceFunctionParameters.map {
if (it in interfaceFunctionParametersMap) {
interfaceFunctionParametersMap[it]
} else {
when (it.type.classifier) {
Boolean::class -> false
Byte::class -> 0.toByte()
Short::class -> 0.toShort()
Int::class -> 0
Long::class -> 0L
Float::class -> 0f
Double::class -> 0.0
Char::class -> '\u0000'
else -> null
}
}
}.toTypedArray(),
continuation,
interfaceFunctionParameters.withIndex().fold(0) { acc, (i, param) ->
acc or if (param in interfaceFunctionParametersMap) 1 shl i else 0
}, // mask
null, // marker
)
}
println(x)
but it never finishes the continuation nor prints the return valueephemient
01/10/2025, 4:45 AMkotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
or handle the non-COROUTINE_SUSPENDED
case yourselfJosh Feinberg
01/10/2025, 10:07 PMJosh Feinberg
01/10/2025, 10:07 PM