シチュエーション
これは、Groovyを2.2.x系から2.3.x以上に上げた時に、
「Method 'foo' from class 'Hoge' does not override method from its superclass or interfaces but is annotated with @Override」
と言われてしまうケースに該当する。
原因
2.2.xだと@Overrideアノテーションを親クラスのメソッドと型が違う場合でも使えてしまう事がある。
見つけたのは次のような総称型(ジェネリクス=Generics)を使っているケース。
package jp.eiya.aya;
public abstract class AbsEcho<T>{
public abstract T echo(T obj);
}
このような抽象クラスに対して、つぎのようなテストを書いたとする。
package jp.eiya.aya
import spock.lang.Specification
class AbsEchoTest extends Specification{
static class StringEchoForTest extends AbsEcho<String>{
@Override
String echo(Object obj){ // << ココ
obj.toString()
}
}
static stringEcho = new StringEchoForTest()
def 'Can echo an Strgng value?'(){
expect:
stringEcho.echo(value) == value
where:
value << ['a','b','c']
}
}
上記のStringEchoForTestクラスはAbsEchoクラスを継承し、echoメソッドをOverrideしているが、よくよく見るとechoの引数がObjectである。
親クラスのechoメソッドの定義は、public abstract T echo(T obj);
なので、正しくはString
を引数とするメソッドでなければならないはずだが、2.2.x系だとエラーにならない。
もしこういうコードを書いていると、2.3.x系かそれ以上にアップグレードしようとした時にエラーとなる。
解決方法
そもそも間違っているので、正しい引数の型を受けるように修正する必要がある。
今回はたまたま発見して、うおぉぅ となったので共有しておく。