2

この基本クラスがあるとしましょう:

abstract public class Base {
    abstract public Map save();
    abstract public void load(Map data);
}

驚いたことに、派生クラスでこれを行うことができました。

public class Derived extends Base {
    @Override
    public Map<String, String> save() {    //Works
        ...
    }
    ...
}       

しかし、私はこれを行うことができませんでした:

public class Derived extends Base {
    @Override
    public void load(Map<String, String> data) {    // Fails
        ...
    }
    ...
}       

ここで何が起きてるの?特殊な戻り値の型を使用できるのに、特殊なパラメーターの型を使用できないのはなぜですか?

さらにややこしいのは、 の元の宣言を保持するとload、それをより特殊な型に割り当てることができるということです。

public class Derived extends Base {
    @Override
    public void load(Map data) {
        Map<String, String> myData = data;   // Works without further casting
        ...
    }
    ...
}       
4

3 に答える 3

11

特殊な型から生の型への暗黙的な変換があります。生の型を使用している人は何も仮定できないため、これは常に「安全」です。したがって、メソッドから raw がMap返されることを期待している人は、. が返されても気にしませんMap<String, String>

生の型から特殊な型への暗黙的な変換はありませんMap。誰かが生を渡した場合load、文字列以外のキーと値を持つ可能性があります。の基本型宣言により、これは完全に合法ですload

ジェネリックはさておき、メソッドは次のようになります。

public abstract class Base
{
    public abstract Object save();
    public abstract void load(Object x);
}

public class Derived extends Base
{
    @Override
    public String save() { ... } // Valid

    @Override
    public void load(String x) // Not valid
}

ジェネリックが削除されたので、saveここで呼び出しが問題ない理由は明らかですが、load呼び出しはそうではありませんか? このことを考慮:

Base b = new Derived();
Object x = b.save(); // Fine - it might return a string
b.load (new Integer(0)); // Has to compile - but the override wouldn't work!
于 2009-04-22T11:40:42.933 に答える
2

load(Map<String, String> data)次のように特殊化されたクラスの代わりに基本クラスを使用すると、これに簡単に違反する可能性があるため、パラメーターをに変更することはできません。

Base base = new Derived()
base.load(new HashMap<Integer, Integer>());

これは、deriveded の load-method を呼び出しますが、宣言に違反しています。ジェネリックはコンパイル時にのみチェックされるため、そのエラーを検出することはできません。

戻り値は、スーパークラスよりもサブクラスに特化している限り問題ありません。

于 2009-04-22T11:39:38.100 に答える
0

問題は、一般に、引数の型によって区別される 2 つのメソッドを持つことができるということだと思います。正確に 1 つを選択する必要があります。これには、消去されていない型を調べる必要があります。これは、2 つのload方法が区別できることを意味します。したがって、区別可能なメソッドがありますが、消去された形ではメソッドは 1 つしか存在しません。

(Java では) 共変の戻り値の型を持つことができますが、戻り値の型によるオーバーロードはできないため、これは戻り値の型の問題ではありません。

于 2009-04-22T12:26:53.697 に答える