为什么在Groovy(版本2.4.5)中调用super会错过父类?
鉴于课程安排如下:为什么在Groovy(版本2.4.5)中调用super会错过父类?,groovy,Groovy,鉴于课程安排如下: class GrandParent { String init() { return "GrandParent init, " } } class Parent extends GrandParent { String init() { return super.init() + "Parent init, " } } class ChildInitAndVisit extends Paren
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
这与ChildInitAndVisite类的行为形成对比,与Groovy-I checked 2.3.4的旧版本下的行为不同
这是一个Groovy bug吗?或者我应该做些不同的事情吗?我相信这就是Groovy的(运行时/动态调度)行为。在运行时,将使用来自祖父母的init()
,而不是来自Parent的init()
class ChildVisitOnly extends Parent {
String visit() {
return init() + "Child visit"
}
}
Java方式(编译时调度)使用它的一种方法是在ChildVisitOnly
类上使用@CompileStatic
@CompileStatic
class ChildVisitOnly extends Parent {
String visit() {
return super.init() + "Child visit"
}
}
以上将给出您期望的结果
另一种方法是在ChildVisitOnly
中显式地使用init()
或this.init()
,而不是@CompileStatic
来强制使用init()
class ChildVisitOnly extends Parent {
String visit() {
return init() + "Child visit"
}
}
这显然偏离了Groovy 2.3.4的行为,但我还没有找到一个关注这一差异的相关问题。我很好奇,看看是否有人能给我指出导致行为改变的缺陷。:) 在我看来,这是一个错误super.init()
必须调用父#init()。Groovy使用的基于实例的多方法意味着,当考虑父类中的方法调用时,子类中的方法在父类的范围内变得可见,同时处理子类的实例。但是多方法不会覆盖Java意义上的方法。这意味着,ChildVisitOnly中的init方法必须来自父级,而不是祖父母。Groovy根本无法理解,如果您编写super.init()
,并且不重写init()方法,它就不应该接受init方法声明类的父类