如果该成员函数存在,如何引用或调用该成员函数

How to make a reference of or call a member function if that member function exists

我想检查对象上是否存在具有特定名称的成员函数,它是否确实调用了该成员函数或引用了该成员函数。

这里我没有对象的类型,即对象可能没有实现任何接口,但有一个成员函数 cancel()。

我使用 this 方法(反射)来检查成员函数是否存在,即 if (object::class.members.any { it.name == "cancel" }) 并且当此语句 returns 为真时,我确定该方法确实存在但编译器仍然不确定 'cancel' 方法是否存在于对象中

fun canceller(object: Any): KFunction<Any>?
{
    var canceller: KFunction<Any>? = null

    // check if object has member function 'cancel'
    if (object::class.members.any { it.name == "cancel" })
    {
        // make reference of that member function and return it
        canceller = object::cancel  //cancel is still not recognized as a member function and gives an error that "Unresolved reference: cancel"

        // or just call it now
        // object.cancel()
    }
    return canceller
}

我希望 canceller 变量应该分配给 value.cancel(),但编译器不确定对象中是否存在 cancel() 函数(错误 "Unresolved reference: cancel"),即使在我们提供之后也是如此检查 if 语句

我认为您可以为此目的使用反射。

myObject.javaClass.kotlin.members.any { it.name == "cancel" }

表达 "object that has all the variables" 思想的更好方法是定义接口并实现所有这些对象

interface Achiever { val name: String }

不应该这样使用。如果您在编译时不知道在运行时要处理什么,则可以使用反射。一些例子:

  • 您需要使用在某些属性文件中配置的类型 (Class.forName("someTypeString").newInstance())
  • 您已经编写了一个实用程序来提取对象的内容以进行调试
  • 您需要访问您并不真正可见的代码(您无法轻松访问但需要访问的私有字段)
  • 还有很多...但大部分时间都很特别use-cases

现在您所显示的是函数参考 (object::cancel)。为了使用函数引用,编译器必须知道 object 的类型并且 cancel 函数必须存在于该类型。由于 objectAny 类型并且 if 条件仅在运行时相关,编译器不知道有可用的 cancel 函数,因此编译失败.

请注意,如果您没有做任何特殊的事情,您应该检查一个普通的 type/interface。因此,例如,如果您的对象实现了一个接口 Cancellable,您可以将代码更改为如下内容:

fun canceller(object: Any): KFunction<Any>? {
  var canceller: KFunction<Any>? = null

  // check if object is of type Cancellable
  if (object is Cancellable) {
    // make reference of the Cancellable::cancel-function
    canceller = object::cancel  // smart-cast acting

    // or you could also call it directly: object.cancel()
  }
  return canceller
}

或者您可以完全保留该功能并最终得到类似的东西:

val someObj : Cancellable = ...
// somewhere later:
someObj.cancel()

反射相当昂贵,如果您不完全确定它有什么用,则不应使用它。

如果你真的知道你在做什么......那么好吧......当然也可以通过反射调用该函数,如果你通过反射请求函数的存在,你也必须调用它通过反思:

object::class.members.first {
  // note: I am using just the first function... if there are several, you need to check which one to use (parameter/type)
          it.name == "cancel" 
   }
   .call(object)