[Groovy] this 语义的陷阱

探讨了Groovy中父类私有方法调用其他私有方法时的问题,特别是在子类继承的情况下面临的异常情况。分析了Groovy与Java处理机制的不同,并指出此问题在Groovy 2.0中将会得到解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

groovy 中 this 的语义有问题。下面的代码会报异常,说 secret2 方法找不到:

new Sub().doSomething()

class Parent {
def doSomething() {
secret().secret2()
}

private def secret() {
println "secret"
this
}

private def secret2() {
println "secret 2"
this
}
}

class Sub extends Parent {
def doSomething() {
super.doSomething()
}
}

将 Parent#doSomething() 修改一下,打印出 secret() 的返回值类型后得到:

def doSomething() {
println secret()
}

输出:
[quote]secret
class Sub[/quote]

this 指向的是子类型。所以不要把 chaining 用在 private 方法上。因为子类型无法访问到父类型的 private 方法,返回 this 就会引起子类型报错。

[size=x-large][b]补[/b][/size]
在 Java 试验的结果是 println 显示 this.getClass() 为 Sub,与上面的 Groovy 代码结果一致。但是 Java 下调用是成功的。也就是说 Java 并不是像表面上 println 显示的那样简单地直接使用 Sub 的实例去调用 secret2(),而是隐式用的 Parent 实例去调用 secret2()。Groovy 在动态调用方法时没有考虑到这点,直接用 "this" 去调,导致找不到 secret2() 这个函数。

[size=x-large][b]补2[/b][/size]
这个问题现在看来比较严重。如果父类中的私有方法调用了另一个私有方法,那么子类如果在运行时用到了这个父类的私有方法,就会抛异常。示例:

new Sub().doSomething()

class Parent {
def doSomething() {
secret()
}

private def secret = {
secret2()
}

private def secret2 = {
println "secret 2"
}
}

class Sub extends Parent {
def doSomething() {
super.doSomething()
}
}

所以,父类的私有方法不能调用其它的私有方法。

[size=x-large][b]补3[/b][/size]
在 codehaus 上找到了与这个问题本质上一样的 bug report:[url]http://jira.codehaus.org/browse/GROOVY-3073[/url]。Jochen Theodorou 说这是因为 Groovy 当前的 MOP(Meta Object Protocol)不支持造成的。预计会在 Groovy 2.0 中解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值