kotlin - Pass method reference to function - reflection

Let's say I have the following Java class:
public class A {
public Result method1(Object o) {...}
public Result method2(Object o) {...}
...
public Result methodN(Object o) {...}
}
Then, in my Kotlin code:
fun myFunction(...) {
val a: A = ...
val parameter = ...
val result = a.method1(parameter) // what if i want methodX?
do more things with result
}
and I want to be able to choose which methodX will be called inside myFunction. in Java, I would pass A::method7 as an argument and call it. in Kotlin it doesn't compile. How should I solve it in Kotlin?

You can also pass the method reference in Kotlin (without needing the heavy hammer that is reflection):
fun myFunction(method: A.(Any) -> Result) {
val a: A = ...
val parameter = ...
val result = a.method(parameter)
do more things with result
}
myFunction(A::method1)
myFunction {/* do something in the context of A */}
This declares method as part of A, meaning you can call it with normal object.method() notation. It Just Works™ with the method reference syntax.
There's also another form that works with the same call syntax, but makes A more explicit:
fun myFunction(method: (A, Any) -> Result) { ... }
myFunction(A::method1)
myFunction {a, param -> /* do something with the object and parameter */}

You can actually do this exactly like you wanted to:
fun myFunction(kFunction: KFunction2<A, #ParameterName(name = "any") Any, Result>) {
val parameter = "string"
val result: Result = kFunction(A(), parameter)
//...
}
myFunction(A::method1)
myFunction(A::method2)

Related

how to create kotlin infix function with 2 words?

fun main(args: Array<String>) {
var arr = IntArray(10)
println(arr get size) // prints size of arr
arr print all //prints all elements of arr
I think "get size" is 2 infix function, get and size, and get function takes argument of size function result, and prints take argument of "all" function result, any solutions?
What you are trying to achieve doesn't make much sense and you shouldn't implement such things in production. Just for educational propose, something similar can be achieved:
infix fun <T> Array<T>.get(parameter: String): Int {
when(parameter) {
"size" -> return this.size
}
throw NotImplementedError()
}
and usage would be:
println(array get "size")
Edit:
The version where you would call array get size will look the following:
enum class GetType { size }
infix fun <T> Array<T>.get(parameter: GetType): Int {
when(parameter) {
GetType.size -> return this.size
}
However if you want to call size instead of GetType.size then you need to import everything in the enum class:
import GetType.*

Recursive anonymus function in kotlin

Im making this anonymus function, and i need it to call itself. Is there any way to do it? I tried the code below, which didnt work...
val example:Char = fun () : Char {
//Some code
if(condition) {
return this();
}
}
What should i replace 'this()' with?
Im pretty new to kotlin, so it would be really helpful with a response
You can't name anonymous functions (either with this syntax, or as a lambda) in Kotlin, and therefore you can't make them recursive either, because you have know way to reference themselves.
If you need recursion, you'll have to create a regular function, and call that:
fun helper() : Char {
if (condition) {
return helper();
}
...
}
val example = helper()
The good news is that you can basically create a regular, named function in any scope. They can be top level outside classes, class members, or just local functions nested within other functions. Wherever you can write down val example = ..., you can also create a function.
Calling an anonymous function sound complicated as there is no name to call it with :)
As I'm learning Kotlin myself at the moment, I tried something and came up with this, hope it helps:
import kotlin.test.Test
import kotlin.test.assertEquals
class StackOverflow51233329 {
#Test
fun test() {
var letter = 'A'
lateinit var example: () -> Char
example = {
letter++
if (letter >= 'C') letter else example()
}
assertEquals('C', example())
}
}
If you want to avoid using lateinit, you could use the Y combinator, which can be used to enable recursion when recursion is impossible directly. Declare this globally:
class RecursiveFunc<T, R>(val f: (RecursiveFunc<T, R>) -> (T) -> R)
fun <T, R> y(f: ((T) -> R) -> (T) -> R): (T) -> R {
val rec = RecursiveFunc<T, R> { r -> f { r.f(r)(it) } }
return rec.f(rec)
}
This code was taken from Rosetta Code. You use it like this:
val fac = y { f: ((Int) -> Int) ->
{ n: Int ->
if (n <= 1) 1 else n * f(n - 1)
}
}
println(fac(10))
f is the recursive function here, with a signature of (Int) -> Int. The rest of the function is pretty much the same as usual, but in lambda form. You can even use the usual function syntax if that's more familiar:
val fac = y { f: (Int) -> Int ->
fun(n: Int): Int {
return if (n <= 1) 1 else n * f(n - 1)
}
}

why SomeClass::class is KClass<SomeClass> but this::class is KClass<out SomeClass>

I want to print values of properties of my class.
fun print() {
val cl = this::class
cl.declaredMemberProperties.filter {it.visibility != KVisibility.PRIVATE}.forEach {
println("${it.name} = ${it.get(this)}")
}
}
When I try to build this code I get compiler error:
Error:(34, 40) Kotlin: Out-projected type 'KProperty1<out SomeClass, Any?>' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
When I change this to class name SomeClass everything is fine
fun print() {
val cl = SomeClass::class
cl.declaredMemberProperties.filter {it.visibility != KVisibility.PRIVATE}.forEach {
println("${it.name} = ${it.get(this)}")
}
}
So the problem is that compiler changers type of this::class to KClass<out SomeClass> instead of using KClass<SomeClass>. Any idea why does it happen?
The reason for this difference is that, when you use the SomeClass::class reference, it is sure to be the class token representing SomeClass and not one of its possible derived classes, therefore it is KClass<SomeClass> without type projections.
But this::class written in a function of an open or abstract class or an extension function can return a class token of a derived class, therefore, to ensure type safety, the type is out-projected: KClass<out SomeClass> means that the actual type argument can be SomeClass or its subtype.
Example:
open class A {
fun f() {
println(this::class) // KClass<out A> because it can be KClass<B>
}
}
class B : A()
B().f()

How can I get the name of a Kotlin property?

I have the following function to access a property's delegate. It uses Kotlin reflection to get a property's name and Java reflection to get the field.
fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
The method is used like this:
val delegate = a.getDelegate(A::b)
However, I would prefer to use it like this:
val delegate = a.b.delegate
The problem with the code above is getting the property name of a.b and getting the instance a from a.b. From what I know about Kotlin, this is probably not possible, however I'd like to see if I can clean up my function at all.
To give a bigger picture of what I'm trying do here's my complete code. I want an observable delegate to which I can add and remove observers using the delegate reference and without creating addition variables.
fun Any.addObservable<T>(prop: KProperty<T>, observer: (T) -> Unit) {
getObservableProperty(prop).observers.add(observer)
}
fun Any.getObservableProperty<T>(prop: KProperty<T>): ObservableProperty<T> {
return getDelegate(prop) as ObservableProperty<T>
}
fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
class ObservableProperty<T>(
initialValue: T,
initialObservers: Array<(T) -> Unit> = emptyArray()) : ReadWriteProperty<Any?, T> {
private var value = initialValue
public val observers: MutableSet<(T) -> Unit> = initialObservers.toHashSet()
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value
}
public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
this.value = value
observers.forEach { it(value) }
}
}
class A() {
var b by ObservableProperty(0)
}
fun main(args: Array<String>) {
val a = A()
a.addObservable(A::b) {
println("b is now $it")
}
a.b = 1
a.b = 2
a.b = 3
}
Edit:
I just realized that the function also isn't strict because the property delegate field name is referenced by KProperty name, which doesn't require a strong reference to the enclosing class. Here's an example to demonstrate the problem:
class A() {
var foo by ObservableProperty(0)
}
class B() {
var foo by ObservableProperty(0)
}
fun main(args: Array<String>) {
val a = A()
a.addObservable(B::foo) {
println("b is now $it")
}
a.foo = 1
a.foo = 2
a.foo = 3
}
This compiles and runs without error because A::foo and B::foo both result in a field string of "foo$delegate.
Right now reflection is all we can do to get to the delegate object. We are designing a language feature to have direct access to delegate instance, but it's long way to go.
This is how you get the name of a Kotlin Property (although only with an instance of the class). This part will be useful to anyone arriving at this question purely based off its title.
class Stuff(val thing: String)
val stuff = Stuff("cool stuff")
val thingFieldName = "${stuff.thing}\$delegate"
// value of thingFieldName is now "thing"
In terms of getting the delegate itself easier, they say you can now do this:
class Foo {
var bar: String by ReactiveProperty<String>()
}
val foo = Foo()
val bar = foo.bar
val barDelegate = ... // foo.bar$delegate
See ticket.

Does `productElement(i)` on a case-class use reflection?

Considering the following Scala snippet:
case class Foo(v1: String, v2: Int, v3: Any)
def inspect(p: Product) =
(0 until p.productArity).foreach(i => println(p.productElement(i)))
inspect(Foo("Moin", 77, null))
Does the invocation of inspect() here means that reflection is used (in whatever way)?
I'd like to somehow be able to access the fields of a case-class without having to explicitly refer to them, e.g. by foo.v1 and I'd favour a solution that does not require reflection since I expect that it entails some overhead.
No reflection will be used for the productElement. It's a compiler trick. Adding case before a class doesn't just create a companion object (with apply method and so on, see http://www.scala-lang.org/node/258), it also extends the class from the trait Product. The compiler creates implementations of the abstract methods productArity and productElement.
The output of scalac -print Foo.scala shows it:
... case class Foo extends java.lang.Object with ScalaObject with Product {
...
override def productArity(): Int = 3;
override def productElement(x$1: Int): java.lang.Object = {
<synthetic> val temp6: Int = x$1;
(temp6: Int) match {
case 0 => {
Foo.this.v1()
}
case 1 => {
scala.Int.box(Foo.this.v2())
}
case 2 => {
Foo.this.v3()
}
case _ => {
throw new java.lang.IndexOutOfBoundsException(scala.Int.box(x$1).toString())
}
}
};
...
}
If you want to access to the fields without reflection, you can use the method productElement from the trait Product
scala> case class Foo(v1: String, v2: Int, v3: Any)
defined class Foo
scala> val bar = Foo("Moin", 77, null)
bar: Foo = Foo(Moin,77,null)
scala> bar.productElement(0)
res4: Any = Moin
scala> bar.productElement(1)
res5: Any = 77
scala> bar.productElement(2)
res6: Any = null

Resources