Kotlin is it possible to delegate function or function parameters?

1k views Asked by At

I want to have for example:

class Foo {
   fun doSomething(arg1: String, arg2: String, arg3: Boolean)
}

class FooDelegate {
   //different fun name
   fun execute by Foo::doSomething
}

Either with reflection or other way.

What I currently have is:

class FooDelegated<R>(
    private val func: KFunction<R>
) {
    fun execute(vararg params: Any) = func.call(*params)
}

So that I can call

FooDelegated(Foo::doSomething).execute("1", "2", true)

However I require to send parameters which are not really know. I would like my compiler to know which parameters can be sent. Else, I can write the following and it won't fail until run time:

   FooDelegated(Foo::doSomething).execute("1", "2", "new argument", false)

NOTE that I want it to have different names, not by using interfaces.

1

There are 1 answers

4
broot On

Instead of creating execute() function, you can create execute property and keep a function reference there. Then you can use it almost like it is a function:

class FooDelegate {
    val execute = Foo::doSomething
}

fun main() {
    FooDelegate().execute(Foo(), "hello", "world", true)
}

Or:

class FooDelegate {
    private val foo = Foo()
    val execute = foo::doSomething
}

fun main() {
    FooDelegate().execute("hello", "world", true)
}

You can also create a wrapper around KFunction to hide its properties like annotations, isFinal, etc., but keep its operator fun invoke functionality. This would give you more flexibility on what you can do with these functions. It would also make possible to replace execute property with a true execute() function. However, you would need to create a separate wrapper per number of properties. It could look like this:

fun main() {
    delegate(Foo()::doSomething).execute("hello", "world", true)
    delegate(Foo::doSomething).execute(Foo(), "hello", "world", true)
}

fun <P0, P1, P2, R> delegate(func: (P0, P1, P2) -> R) = FunctionDelegate3(func)
fun <P0, P1, P2, P3, R> delegate(func: (P0, P1, P2, P3) -> R) = FunctionDelegate4(func)

class FunctionDelegate3<P0, P1, P2, R>(
    private val func: (P0, P1, P2) -> R
) {
    fun execute(p0: P0, p1: P1, p2: P2): R = func(p0, p1, p2)
}

class FunctionDelegate4<P0, P1, P2, P3, R>(
    private val func: (P0, P1, P2, P3) -> R
) {
    fun execute(p0: P0, p1: P1, p2: P2, p3: P3): R = func(p0, p1, p2, p3)
}

Still, it sounds like a very strange thing to do. Like you trying to create programming language inside another programming language.