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

时间:2019-05-18 05:33:44

标签: function object kotlin reference member

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

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

我使用了this方法(反射)来检查成员函数是否存在,即if (object::class.members.any { it.name == "cancel" }),并且当该语句返回true时,我确定该方法确实存在,但是编译器仍不确定' 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语句

2 个答案:

答案 0 :(得分:0)

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

myObject.javaClass.kotlin.members.any {it.name ==“取消”}

表达“具有所有变量的对象”的想法的更好方法是定义接口并实现所有这些对象

interface Achiever {val name:String}

答案 1 :(得分:0)

这并不是要像这样使用。如果在编译时不知道在运行时要处理什么,则可以使用反射。一些示例:

  • 您需要使用在某些属性文件(Class.forName("someTypeString").newInstance())中配置的类型
  • 您已经编写了一个实用程序,可以提取对象的内容以进行调试
  • 您需要访问对您而言并不真正可见的代码(您无法轻松访问但需要的私有字段)
  • 更多...但是大多数时候非常特殊的用例

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

请注意,如果您没有做任何特别的事情,您应该检查一个通用的类型/接口。因此,例如,如果您的对象实现接口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)