9

このインターフェースがある場合:

public interface Foo {
    void bar();
}

なぜこのように実装できないのですか?

public class FooImpl implements Foo {
    @Override
    public Object bar() {
         return new Object();
    }
}

void はすべてと共変であるべきだと思われます。何か不足していますか?

編集:コンパイルできないという技術的な理由ではなく、設計の正当性を探していることをより明確にする必要がありました。void をすべてに対して共変にすることにはマイナスの結果がありますか?

4

8 に答える 8

13

voidJLSがそう言っているので、void共変であるだけです:

次の条件が満たされる場合に限り、戻り値の型 R1 を持つメソッド宣言 d1 は、戻り値の型 R2 を持つ別のメソッド d2 の戻り値の型で代用可能です。

  • R1 が の場合void、R2 はvoidです。

  • R1 がプリミティブ型の場合、R2 は R1 と同じです。

  • R1 が参照型の場合:

    • R1 が R2 のサブタイプであるか、R1 がチェックなしの変換 (§5.1.9) によって R2 のサブタイプに変換できるか、または

    • R1 = |R2|

于 2013-01-08T16:28:45.240 に答える
5

共分散とは、メソッドreturn typeが実行時にSupertype object返すことができる場合、 voidは(または MR NPE によって回答されたそれ自体を除く、その件に関する任意のオブジェクト) ではないことを意味します。sub-type Objectsuper type of java.lang.Object

于 2013-01-08T16:26:53.560 に答える
2

技術的voidには、呼び出し元がスタック レイアウトを知る必要があるため、共変の戻り値の型にすることはできません。オブジェクトを返す関数を呼び出すと、INVOKEVIRTUAL/INTERFACE の後のスタックの一番上に object-ref が作成されます。Void戻り値の型はスタックの一番上に何も残さないため、関数はバイナリ非互換です。

したがって、JLS は当然のことながら、それは不可能だと言っています。

于 2013-01-10T16:00:48.593 に答える
1

voidJava ファイル システムの一部ではありません。

型にすると、空の型のようになるので、他のすべての型のサブタイプにする必要があります。つまり、他の型と反変です。

あなたの例では、スーパークラスは何も返さないように指示していますが、サブクラスは何かを返すため、サブクラスはスーパークラスの契約に違反しています。

Object必要に応じて、他の型と共変です。

于 2013-01-08T17:33:45.390 に答える
1

void事実上、何も返さないことを意味します。void *C/C++の a と混同している可能性があります。インターフェイスを次のように変更した場合

public interface Foo {
    Object bar();
}

Java のすべてのオブジェクトは を継承するため、問題なく動作しますObject

したがって、次のようなことができます。

public class FooImpl implements Foo {

    @Override
    public Object bar() {
         return new SpecialObject();
    }

}

SpecialObject obj = (SpecialObject) new FooImpl().bar();
于 2013-01-08T16:26:17.553 に答える
1

オーバーライドされたメソッドの戻り値の型は一致する必要があります。

Foo foo = new FooImpl();
foo.bar();

すべての実装がインターフェイスに準拠しており、同じオブジェクトを返す (またはまったく返さない) 場合を除き、それが何を返すかをどうやって知ることができますか?

于 2013-01-08T16:27:36.197 に答える
0

共変の戻り値の型は通常、より狭い型に置き換えることができるものを意味します。では、 andまたはJavaother の間にそのような関係 (スーパータイプ-サブタイプ) はありません。voidObject

于 2013-01-08T16:28:17.063 に答える
0

これが許可されている場合、これをコンパイルする必要があるかどうかを判断する方法はありません。

 Foo foo = ...
 Object o = foo.bar(); // is it void or an Object ?
于 2013-01-08T16:49:27.513 に答える