0

我想要例如:

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

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

无论是反射还是其他方式。

我目前拥有的是:

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

这样我就可以打电话

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

但是我需要发送不知道的参数。我希望我的编译器知道可以发送哪些参数。否则,我可以编写以下内容,直到运行时才会失败:

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

请注意,我希望它具有不同的名称,而不是使用接口。

4

1 回答 1

2

execute()您可以创建execute属性并在那里保留函数引用,而不是创建函数。然后你可以像使用函数一样使用它:

class FooDelegate {
    val execute = Foo::doSomething
}

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

或者:

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

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

您还可以创建一个包装器KFunction来隐藏其属性,如annotationsisFinal等,但保留其operator fun invoke功能。这将使您更灵活地使用这些功能。它还可以用真正的函数替换execute属性。execute()但是,您需要为每个属性数量创建一个单独的包装器。它可能看起来像这样:

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)
}

尽管如此,这听起来还是一件很奇怪的事情。就像您尝试在另一种编程语言中创建编程语言一样。

于 2021-10-12T20:17:06.313 回答