9

私は次の構造を持っています:

public interface BarReturn {}
public interface FooReturn {}
public interface FooBarReturn extends FooReturn, BarReturn {}

public interface Foo {  
  FooReturn fooBar( );
}

public interface Bar {
  BarReturn fooBar();
}

public interface FooBar extends Foo, Bar {
  FooBarReturn fooBar();
}

Javac は次のメッセージで失敗します。

FooBar.java:2: types Bar and Foo are incompatible; both define fooBar(), but with unrelated return types
public interface FooBar extends Foo, Bar {
       ^
1 error

しかし、Eclipse はそれをうまくコンパイルでき、私が見る限り、コンパイルする必要があります。

これは Eclipse コンパイルまたは javac のバグですか? または、javac をコンパイルするように説得する方法はありますか? 参考までに、私の javac オプションは次のようになります。

javac -d /tmp/covariant/target/classes -sourcepath /tmp/covariant/src/main/java: /tmp/covariant/src/main/java/Foo.java /tmp/covariant/src/main/java/BarReturn.java /tmp/covariant/src/main/java/FooBarReturn.java /tmp/covariant/src/main/java/Bar.java /tmp/covariant/src/main/java/FooReturn.java /tmp/covariant/src/main/java/FooBar.java -g -nowarn -target 1.6 -source 1.6
4

6 に答える 6

3

FooBar インターフェイスで Foo と Bar の両方を拡張しています。そのため、互換性のない戻り値の型を持つ 2 つのメソッドを継承しています。Java 共分散は、Liskov 置換に従う場合にのみ許可されます。別名、オーバーライド候補の型は、オーバーライドされた戻り値の型のサブクラスである必要があります。

上記の例では、次のようなものコンパイルされます。

public interface BarReturn {}
public interface FooReturn {}
public interface FooBarReturn extends FooReturn, BarReturn {}

public interface Foo {  
  FooReturn fooBar( );
}

public interface FooBar extends Foo{
  FooBarReturn fooBar();
}
于 2011-08-14T11:38:19.420 に答える
1

同じ問題が発生しましたが、OracleのJDK7を使用すれば問題ないようです。

于 2012-05-16T17:41:08.653 に答える
1

JLS (§9.4.1)は次のように述べています。

インターフェイスは、オーバーライドと同等のシグネチャを持ついくつかのメソッドを継承できます (§8.4.2)。このような状況自体は、コンパイル時エラーの原因にはなりません。インターフェイスはすべてのメソッドを継承すると見なされます。ただし、継承されたメソッドの 1 つは、他の継承されたメソッドに代用可能な戻り値の型である必要があります。そうしないと、コンパイル時エラーが発生します (この場合、throws 句はエラーを引き起こしません)。

したがって、javacは正しいと言えます。しかし、これは私には弁護士用語のように見えるので、間違っている可能性があります。

于 2011-08-14T11:38:33.690 に答える
1

このjavaranch ディスカッションの回答は、javac のバグであることを示唆しているようです。ただし、参照されているバグの URLは機能していないようです。

于 2011-08-14T11:46:41.893 に答える
1

回避策として、次のことができます

interface Foo1 extends Foo {
  FooBarReturn fooBar();
}
interface Bar1 extends Bar {
  FooBarReturn fooBar();
}
public interface FooBar extends Foo1, Bar1 { }

きれいではありませんが、トリックを行う必要があります。

于 2011-08-14T15:37:18.807 に答える
0

これは、Sun の Java 6 コンパイラのバグです。

于 2013-06-24T14:23:44.653 に答える