为什么在Groovy(版本2.4.5)中调用super会错过父类?

时间:2015-11-17 18:43:59

标签: groovy

鉴于以下类别的安排:

class GrandParent { 
    String init() { 
        return "GrandParent init, " 
    } 
}

class Parent extends GrandParent { 
    String init() { 
        return super.init() + "Parent init, " 
    } 
}

class ChildInitAndVisit extends Parent { 
    String init() { 
        return super.init() + "Child init" 
    }

    String visit() { 
        return super.init() + "Child visit" 
    } 
}

class ChildVisitOnly extends Parent { 
    String visit() { 
        return super.init() + "Child visit" 
    } 
}

然后以这种方式使用它们:

iv = new ChildInitAndVisit()
println "ChildInitAndVisit - calling init() -> ${iv.init()}"
println "ChildInitAndVisit - calling visit() -> ${iv.visit()}"

v = new ChildVisitOnly()
println "ChildVisitOnly - calling visit() -> ${v.visit()}"

我希望看到:

ChildVisitOnly - calling visit() -> GrandParent init, Parent init, Child visit

作为最后一个println的输出。相反,我看到了:

ChildVisitOnly - calling visit() -> GrandParent init, Child visit

这与ChildInitAndVisit类的行为形成对比,与旧版本的Groovy下的行为不同 - 我检查了2.3.4。

这是一个Groovy错误吗?或者我应该做些不同的事情?

2 个答案:

答案 0 :(得分:2)

在我看来这是一个错误。 ChildVisitOnly中的super.init()必须调用Parent#init()。

答案 1 :(得分:1)

我相信这是Groovy的multi-methods(运行时/动态调度)行为。在运行时,使用init()中的GrandParent代替init()中的Parent

使用Java方式(编译时调度)的一种方法是在@CompileStatic类上使用ChildVisitOnly

@CompileStatic
class ChildVisitOnly extends Parent { 

    String visit() { 
        return super.init() + "Child visit" 
    } 
}

上面会给出你期望的结果。

另一种方法是明确使用init()中的this.init()ChildVisitOnly代替@CompileStatic强制使用init()中的Parent

class ChildVisitOnly extends Parent { 

    String visit() { 
        return init() + "Child visit" 
    } 
}

这明显偏离了Groovy 2.3.4的行为,但我还没有找到一个关注这种差异的相关问题。我很想知道是否有其他人可以指出我的行为发生变化的缺陷。 :)