1

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.

3
  • How would fun execute by Foo::doSomething ever work? You don't even have an instance of Foo! Do you expect execute to take an extra parameter of Foo? Commented Oct 12, 2021 at 19:45
  • Also, what is wrong with fun execute(arg1: String, arg2: String, arg3: Boolean) = someFoo.doSomething(arg1, arg2, arg3)? Commented Oct 12, 2021 at 19:53
  • I can't think of any possible way to do this at compile time with annotations. Reflection is useless since that is done at runtime. I think you would need a customized Kotlin compiler to achieve this. Commented Oct 12, 2021 at 19:56

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Mm I understand however it doesn't work as I need. What I am really looking forward is to send Foo:doSomething as a parameter, so that the Delegate can use execute to call any other function defined as a parameter. I tryed using a KFunction in the val but it doesn't seem to be able to infer the parameters.
For example: Delegate(foo::doSomething).execute("1", "2", false) . I'm exploring some possibilities for an architecture, to create intermediate components without having to create an "empty" class just to have the intermediate component
I updated my answer.
Thanks, I also thought about that and creating FunctionN variants, then I thought that even so the argument names won't be identified as the original names, but only as p0, p1, p2, etc ; and will probably be more confusing to devs :P. Thank you anyway!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.