使用方法参考时的常规方法作用域

Jef*_*rey 1 methods groovy dynamic

我有一个普通的类,该类查找方法引用,然后调用它。被调用的方法是私有方法。当实际的类是子类的实例时,即使实际调用它的是父类中的公共方法,它也会引发一个错误,即找不到私有方法。

在这种情况下,我显然可以pMethod2()直接调用并且可以正常工作,但是我试图理解为什么它不能按书面要求工作,并且是否有一种方法可以纠正它。

class Parent {

  def pMethod1() {
    def m = this.&pMethod2
    m() // this call fails if the calling class is of type Child
  }


  private def pMethod2() {}

  public static void main(String[] args) {
    new Child().pMethod1();
  }
}

class Child extends Parent {}
Run Code Online (Sandbox Code Playgroud)

Ste*_*nar 5

这有点令人困惑,特别是如果您习惯于C / C ++。在Groovy中使用“。&”运算符时得到的不是地址,而是MethodClosure的实例。

MethodClosure对象包含一个所有者和一个委托对象,在解析要调用的方法时使用。在您的示例中,所有者和委托对象将是“ this”,它是Child的一个实例。调用方法只是存储为字符串。

所以,任务

m = this.&pMethod2
Run Code Online (Sandbox Code Playgroud)

只是一种速记方式

m = new MethodClosure(this, "pMethod2")
Run Code Online (Sandbox Code Playgroud)

调用m()闭包时,它将尝试(在运行时)通过分别在所有者和委托对象中查找名为“ pMethod2”的方法来解析该方法。由于所有者和委托人是Child的实例,因此它将不会在Parent中找到私有方法。

为了使示例工作,必须确保该方法对闭包的所有者和/或委托可见。

这可以通过多种方式完成,例如,将pMethod2的访问修饰符更改为protected,或者通过创建具有Parent实例的闭包;像这样的东西:

m = new Parent().&pMethod2
Run Code Online (Sandbox Code Playgroud)

请注意,在实际上可见pMethod2的方法中创建MethodClosure实例是无关紧要的。在可见的方法中调用闭包也无关紧要。该方法对MethodClosure的所有者或委托人不可见,这是解决方法时所用的方法。