Skip to content

Instantly share code, notes, and snippets.

@nobeans
Last active May 15, 2018 04:30
Show Gist options
  • Save nobeans/0655a131ab3c458f99916655809bd547 to your computer and use it in GitHub Desktop.
Save nobeans/0655a131ab3c458f99916655809bd547 to your computer and use it in GitHub Desktop.
GroovyのTraitのコーナーケースを踏んだ?
// in Groovy 2.4.14
import groovy.transform.CompileStatic
// このようなprivate staticメソッドを使うメソッドをもつtraitに対して...
@CompileStatic
trait Trait {
String traitMethod() { _traitMethod() }
private static String _traitMethod() { "TRAIT" }
}
// 直接traitを実装するとなにも問題ない
@CompileStatic
class TraitImpl implements Trait {
String traitImplMethod() { "IMPL-${traitMethod()}" }
}
assert new TraitImpl().traitImplMethod() == "IMPL-TRAIT"
// 一段クラス階層を経由すると使うと...
@CompileStatic
class Parent implements Trait {
String parentMethod() { "PARENT-${traitMethod()}" }
}
@CompileStatic
class Child extends Parent {
String childMethod() { "CHILD-${parentMethod()}" }
}
GroovyAssert.shouldFail(MissingMethodException) {
assert new Child().childMethod() == "CHILD-PARENT-TRAIT"
}
// => trait上のprivate staticメソッドが見つからなくなる!
// groovy.lang.MissingMethodException: No signature of method: Child._traitMethod() is applicable for argument types: () values: []
// Possible solutions: traitMethod(), parentMethod()
// at Trait$Trait$Helper.traitMethod(ConsoleScript35:5)
// at Parent.traitMethod(ConsoleScript35)
// at Parent.parentMethod(ConsoleScript35:19)
// at Child.childMethod(ConsoleScript35:23)
// at Child$childMethod.call(Unknown Source)
// at ConsoleScript35.run(ConsoleScript35:26)
// privateではないstaticだったり、staticではないprivateだったりすれば問題ない。
@CompileStatic
trait Trait2 {
String traitMethod() { _traitMethod() }
static String _traitMethod() { "TRAIT" }
}
@CompileStatic
class Parent2 implements Trait2 {
String parentMethod() { "PARENT-${traitMethod()}" }
}
@CompileStatic
class Child2 extends Parent2 {
String childMethod() { "CHILD-${parentMethod()}" }
}
assert new Child2().childMethod() == "CHILD-PARENT-TRAIT"
@CompileStatic
trait Trait3 {
String traitMethod() { _traitMethod() }
private String _traitMethod() { "TRAIT" }
}
@CompileStatic
class Parent3 implements Trait3 {
String parentMethod() { "PARENT-${traitMethod()}" }
}
@CompileStatic
class Child3 extends Parent3 {
String childMethod() { "CHILD-${parentMethod()}" }
}
assert new Child3().childMethod() == "CHILD-PARENT-TRAIT"
// ちなみに宗教上の理由でCompileStaticをつけているけれど、外しても事象は同じ。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment