【问题标题】:How to get Methods from KClass in Kotlin如何从 Kotlin 中的 KClass 获取方法
【发布时间】:2021-03-03 08:58:41
【问题描述】:

在 java 中,当我有一个 Class 实例时,我有一个返回 Method 的 getMethod,它非常易于使用。 正如我所见,Kotlin 让生活变得更加艰难,因为这种方法不存在。除了将 KClass 转换为 Class 然后像在 Java 中一样使用它之外,有没有一种很好的方法来获得特定的方法?

【问题讨论】:

  • 是否需要通过字符串名称获取方法?否则,您可以使用::methodName
  • 否则,您可以使用class.members.single { it.name == "theFunctionName" }获取KCallable
  • 是的,我需要姓名。顺便说一句,当我尝试以下操作时, ::methodName 不起作用: val str:String ="dsasa" var kclass : KClass = str::class str.toUpperCase()
  • 我没有完全按照您的尝试进行操作,可能是因为注释格式,但如果您也想询问,也可以将其编辑到问题中。
  • @Tenfour04,我都明白了!谢谢!你应该写一个正式的答案,这样我就可以奖励你:) 你是 lambda 表达式的大师。只有两个小而重要的问题,1. 这种语法是否将实例绑定到函数? 2.成员集合中是否包含companion对象的方法?

标签: java android class kotlin reflection


【解决方案1】:

假设你有这个类:

class Test {
    fun sayHello() = println("Hello world")

    companion object {
        fun foo() = println("foo")
    }
}

这为您提供了一个函数实例,您可以使用 invoke() 调用(这是一个运算符函数,因此您可以像使用任何其他函数一样使用括号。如果您使用这样的类名获取函数,则不是绑定到一个实例。所以你在调用时将实例作为第一个参数传递。(如果sayHello()有额外的参数,它们只会在Test的第一个参数之后。)

val sayHelloFunction = Test::sayHello
val test = Test()
helloWorldFunction(test) // same as calling test.sayHello()

您还可以获得绑定到这样的实例的函数引用。它不能在其他 Test 实例上调用。

val test = Test()
val sayHelloFunction = test::sayHello
helloWorldFunction() // same as calling test.sayHello()

上述方法不需要 Kotlin 反射库。

要通过字符串名称获取成员,没有像 Java 的 getMethod 这样的特定函数,因此您必须从成员列表中选择它,即 KCallable。 KCallable 没有operator fun invoke,因此您必须使用call 来调用它,或者将其转换为特定的函数类型(在本例中为(Test) -> Unit)。

val sayHelloCallable = Test::class.members.single { it.name == "sayHello" }
val test = Test()
sayHelloCallable.call(test) // same as calling test.sayHello()

这个没有列出伴生对象的成员,因为那是一个不同的类。为此,您必须获得同伴的课程:

Test.Companion::class.members.single { it.name == "foo" }

我不知道是否有办法通过名称获取实例绑定版本。

至于为什么 KClass 没有方便的 getMethod 函数,我只能猜测是因为 Kotlin 类有很多不同类型的成员(属性、函数、委托、支持字段),也许他们想限制 API 膨胀感觉像single这样的内联过滤功能就够用了。

【讨论】:

  • 非常感谢。很好的解释。也许你可以解释为什么说:“上述方法不需要 Kotlin 反射库”。为什么第一个例子使用反射而第二个不使用?
  • 为了减少 Kotlin 应用程序的编译大小,该库中不太常用的反射功能。
  • 是的。 :: 总是可以在没有反射库的情况下使用。
  • 我的意思是它只是语言的一部分,而不是像需要调用函数的类一样对待。原语在 Java 中的一种方式。
  • 您可以在single lambda 中放入您想要的任何内容来选择您想要的内容,例如.single { it.name == "foo" && it.parameters.size == 2 }
【解决方案2】:

要从KClass 获取Class,您只需调用.java 即可(而.kotlin 则另当别论)。

【讨论】:

    猜你喜欢
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2022-10-24
    相关资源
    最近更新 更多