gpt4 book ai didi

groovy:父类(super class)闭包中的变量范围(MissingPropertyException)

转载 作者:行者123 更新时间:2023-12-02 05:01:03 26 4
gpt4 key购买 nike

我的印象是闭包作为被调用的实际类(而不是实现父类(super class))运行,因此在某些变量不可见时中断(例如父类(super class)中的私有(private)变量)。

例如

package comp.ds.GenericTest2

import groovy.transform.CompileStatic

@CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;

void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}

// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")

// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
this.add(obj)
}
}

b = new ClosureScopeD()

// THIS THROWS groovy.lang.MissingPropertyException: No such property: accessThisPrivateVariable for class: comp.ds.GenericTest2.ClosureScopeD
b.doSomething("abc")

最后一行抛出MissingPropertyException:子类调用父类(super class)的“add”方法,执行“each”闭包,使用“accessThisPrivateVariable”。

我是 groovy 的新手,所以我认为一定有一种简单的方法可以做到这一点,否则闭包似乎会完全破坏在父类(super class)中完成的私有(private)实现的封装......这似乎是一个非常共同需求(父类(super class)实现引用自己的私有(private)变量)

我正在使用 groovy 2.1.3

最佳答案

我发现这是一个很好的引用,描述了 Groovy 变量范围如何工作以及如何适用于您的情况:Closure in groovy cannot use private field when called from extending class

从上面的链接中,我意识到由于您已将 accessThisPrivateVariable 声明为私有(private)的,Groovy 不会自动为该变量生成 getter/setter。请记住,即使在 Java 中,子类也不能直接访问私有(private)变量。

更改您的代码以显式添加 getter/setter,解决了问题:

package com.test
import groovy.transform.CompileStatic

@CompileStatic
class ClosureScopeC {
private List<String> list = new ArrayList<String>()
private int accessThisPrivateVariable = 0;

int getAccessThisPrivateVariable() { accessThisPrivateVariable }
void setAccessThisPrivateVariable(int value ){this.accessThisPrivateVariable = value}

void add(String a) {
list.add(a)
println("before ${accessThisPrivateVariable} ${this.class.name}")
// do something with a closure
list.each {String it ->
if (it == a) {
// accessThisPrivateVariable belongs to ClosureScopeC
accessThisPrivateVariable++
}
}
println("after ${accessThisPrivateVariable}")
}
}

// this works fine
a = new ClosureScopeC()
a.add("abc")
a.add("abc")

// child class
class ClosureScopeD extends ClosureScopeC {
void doSomething(String obj) {
super.add(obj)
}
}

b = new ClosureScopeD()
b.doSomething("abc")

有一个更简单的方法,只需将访问修饰符(应该重命名属性)设置为 protected ,这样子类就可以访问该属性..问题解决了。

protected int accessThisProtectedVariable

澄清您对 Groovy 可能破坏封装的担忧:请放心,它没有。

通过将字段声明为私有(private),Groovy 通过有意暂停公共(public) getter/setter 的自动生成来保留封装。一旦私有(private)化,您现在负责并完全控制子类( protected )或所有对象类(公共(public))如何或是否有办法通过显式添加方法来访问该字段——如果这有意义的话。

请记住,按照惯例,当您的代码引用字段时,Groovy 总是调用 getter 或 setter。所以,像这样的声明:

def f = obj.someField

实际上会调用 obj.getSomeField() 方法。同样:

obj.someField = 5

将调用 obj.setSomeField(5) 方法。

关于groovy:父类(super class)闭包中的变量范围(MissingPropertyException),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16193717/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com