If I define
class MyF : KFunction0<Int> {
override val name: String = "f"
override fun invoke() = 42
override val annotations: List<Annotation>
get() = TODO()
....
}
I can write
val f0: KFunction0<Int> = MyF()
assertEquals("f", f0.name)
but if I try
assertEquals(42, f0())
I get java.lang.ClassCastException: MyF cannot be cast to kotlin.jvm.functions.Function0
How can I define my own implementation of KFunction0
?
I can't work with () -> Int
because I need the name
property.
I'm using Kotlin 1.3.21.
Additionally - it seems that I can run
val f02 = MyF()
assertEquals(42, f02())
My actual use case is Can I convert a Kotlin KFunction1 to a KFunction0 by applying the argument?
It is definitely not a good idea to explicitly implement an internal class from Kotlin JVM. You do not have code completion for that classes in IntelliJ or Android Studio for a reason
You may use callable references instead, to make Kotlin compiler generate all necessary classes for you.
https://kotlinlang.org/docs/reference/reflection.html#callable-references
fun myfun() = 42
val kFunction = ::myfun
println(kFunction.name)
println(kFunction())
The benefit - future version of Kotlin will unlikely to break that code (and may break you inheritor class)
Should you need a longer name for the function, you may declare it like that
fun `my function with long name`() = 43
In Kotlin 1.2 I haven't found KFunction0<T>
but only KFunction<T>
and I was able to do what you wanted:
import kotlin.reflect.*
import kotlin.test.assertEquals
class MyKF : KFunction<Int>{ // In Kotlin 1.3 you can extend KFunction0<Int>
override val annotations: List<Annotation>
get() = listOf()
override val isAbstract: Boolean
get() = false
override val isExternal: Boolean
get() = false
override val isFinal: Boolean
get() = true
override val isInfix: Boolean
get() = false
override val isInline: Boolean
get() = false
override val isOpen: Boolean
get() = false
override val isOperator: Boolean
get() = false
override val isSuspend: Boolean
get() = false
override val parameters: List<KParameter>
get() = listOf()
override val typeParameters: List<KTypeParameter>
get() = listOf()
/**
* I am not sure how get proper return type. So... This KFunction will return kotlin.Number.
*/
override val returnType: KType
get() = Int::class.supertypes[0]
override val visibility: KVisibility?
get() = KVisibility.PUBLIC
override fun call(vararg args: Any?): Int {
return 0
}
override fun callBy(args: Map<KParameter, Any?>): Int {
return 0
}
override val name: String
get() = "f"
// Sience Kotlin 1.3
override fun invoke(): Int {
return 0
}
}
fun main(args: Array<String>) {
val kf = MyKF()
assertEquals("f", kf.name)
assertEquals(0, kf.call())
println(kf.returnType)
println(kf.name)
println(kf.call())
pritnln(kf.invoke())
}
I will update Kotlin to 1.3 later and I'll complete my answer (if it works in Kotlin 1.3).
So where can be your problem? Maybe (just lucky guess) check type based on overriden methods like returnType
?
Edit:
After migrating to Kotlin 1.3 I was able to extend KFunction0<Int>
instead of KFunction<Int>
. The only changes - my class has to also override invoke(): Int
. Still works!
Edit2:
I'm not sure if I just didn't saw KFunction0 in my IDE or is not present in Kotlin below 1.3.