Eitanos30
Eitanos30

Reputation: 1439

How to get Methods from KClass in Kotlin

In java when i have a Class<> instance, i have the getMethod that return a Method and it is very easy to use. As i can see Kotlin makes life harder because such a method doesn't exist. is there a nice way to get a specific method beside of turning the KClass to Class and then using it exactly as in Java?

Upvotes: 3

Views: 5757

Answers (2)

Tenfour04
Tenfour04

Reputation: 93882

Supposing you have this class:

class Test {
    fun sayHello() = println("Hello world")

    companion object {
        fun foo() = println("foo")
    }
}

This gives you a function instance you can call with invoke() (which is an operator function, so you can just use parentheses like with any other function. If you get the function using the class name like this, it is not bound to an instance. So you pass the instance as the first parameter when invoking. (If sayHello() had additional parameters, they would just go after the first parameter of Test.)

val sayHelloFunction = Test::sayHello
val test = Test()
sayHelloFunction(test) // same as calling test.sayHello()

You can also get a function reference that's bound to an instance like this. It cannot be called on other instances of Test.

val test = Test()
val sayHelloFunction = test::sayHello
sayHelloFunction() // same as calling test.sayHello()

The above method doesn't require the Kotlin reflection library.

To get a member by String name, there isn't a specific function like Java's getMethod, so you have to pick it out of the list of members, which are KCallable. KCallable doesn't have the operator fun invoke, so you have to use call to call it, or cast it to a specific function type (in this case it would be (Test) -> Unit).

val sayHelloCallable = Test::class.members.single { it.name == "sayHello" }
val test = Test()
sayHelloCallable.call(test) // same as calling test.sayHello()

This does not list the members of the companion object, as that is a different class. For that you would have to get the companion's class:

Test.Companion::class.members.single { it.name == "foo" }

I don't know if there's a way to get an instance bound version by name.

As for why there's no convenient getMethod function for KClass, I can only guess that because Kotlin classes have so many different types of members (properties, functions, delegates, backing fields), that maybe they want to limit API bloat and feel that the inline filtering functions like single are adequate.

Upvotes: 5

Alexey Romanov
Alexey Romanov

Reputation: 170899

To get a Class from a KClass, you just call .java on it (and .kotlin to go the other way).

Upvotes: 0

Related Questions