0

I have a class that has the type parameter KFunction<*> (It is understood that I will indicate the type of function that I want to work with in the future)

I want a class method to take the same parameters that KFunction has and call subscribers with those arguments. However, I don't know how to get the type of the function parameters. There are delegates in C #. How to do something like this in Kotlin?

My class:

class Event<Function: KFunction<*>> {
    val subscribers = mutableListOf<Function>()

    operator fun plus(increment: Function) {
        subscribers.add(increment)
    }

    // i want arguments as KFunction
    operator fun invoke(args: ???) {
        subscribers.forEach { it(args) }
    }
}

fun c(i: Int) {
    println("result of function c: $i")
}

fun main() {
    val event = Event<KFunction1<Int, Unit>>()
    event + ::c
    event(100) // passing arguments Int from KFunction1<Int, Unit>
}

Is there a way to implement my idea exactly like this?

Danila
  • 53
  • 6
  • You would need reflection to do this, and you would just have to make the invoke argument take varargs. There would be no type-checking at compile time. – Tenfour04 Feb 12 '21 at 14:23

2 Answers2

0

So, it's implied that type, passed as a Function : KFunction<*> type parameter (KFunction1<Int, Unit> in this case) will have its own type parameters (Int and Unit in this case), and you want to declare args parameter as an uncertain amount of parameters with these exact types (excluding the last one, which represents type of function call result)? I believe it's impossible.

The best you can do is to declare args as vararg with Any? type:

operator fun invoke(vararg args: Any?) = subscribers.forEach { it.call(*args) }
0

It seems that the only normal solution to problem is to accept only 1 abstract type of parameters.

class Event<ArgsT> {
    private val subscribers = mutableListOf<(ArgsT) -> Any>()

    operator fun plusAssign(increment: (ArgsT) -> Any) {
        subscribers.add(increment)
    }

    operator fun invoke(params: ArgsT) {
        subscribers.forEach { it(params) }
    }
}

fun c(i: Int, b: Int) {
    println(i + b)
}

data class Data(val i: Int, val b: Int)

fun main() {
    val event = Event<Data>()
    event += { (i, b) -> c(i, b) } // pass arguments using a lambda
    event(Data(2, 5))
}
Danila
  • 53
  • 6