[Groovy] this 語義的陷阱

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 中解決這個問題。
發佈了22 篇原創文章 · 獲贊 0 · 訪問量 2395
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章