2017-11-29 6 views
2

次の例では、戻り値タイプList<? extends IConfigUser>List<ConfigUser>として、getUserList()にオーバーライドすることはできますが、setUserList()のパラメータで同じことを行うことはできません。このクラスがスーパータイプと見なされないのはなぜですか?

ConfigUserは、この場合、IConfigUserのスーパータイプと見なされませんか?

public class Test { 
    public interface IConfigUser { 
    } 

    public interface IConfig { 
     public List<? extends IConfigUser> getUserList(); 
     public void setUserList(List<? extends IConfigUser> list); 
    } 


    public class ConfigUser implements IConfigUser { 
    } 

    // The type Test.Config must implement the inherited abstract method 
    // Test.IConfig.setUserList(List<? extends Test.IConfigUser>) 
    public class Config implements IConfig { 
     @Override 
     public List<ConfigUser> getUserList() { 
     return null; 
     } 

     // The method setUserList(List<ConfigUser> list) of type Test.Config 
     // must override or implement a supertype method 
     @Override 
     public void setUserList(List<ConfigUser> list) 
     { 
     } 
    } 
} 
+0

これが*コンパイルして、誰かがList に渡したとします。 –

答えて

1

あなたがIConfig参照でそのメソッドを呼び出した場合、すなわち、あなたが知っているすべてはあなたがList<? extends IConfigUser>List<ConfigUser>List<? extends IConfigUser>で買ってあげることで、原因共分散に(「特化」)getUserList()の戻り値の型を返すことができます要件が満たされます。

Configの参照で呼び出すと、情報はより具体的ですが、基本的な要件はまだ満たされています。 setUserList(...)

状況が異なっている:それはあなたがList<ConfigUser>することができますが、それはまた、例えば、他の何かすることができList<? extends IConfigUser>のいずれかの「サブクラス」を渡すことができますa List<SomeConfigUser>

Btw listの具体的な総称パラメータがわからないので、setUserList(List<ConfigUser> list)のコンパイラでも、あなたはそのリストからの読み取りのみを許可します。上記の理由と同じ理由で、あなたはわかりません表示される内容はSomeConfigUserのインスタンスのみを追加できるため、ConfigUserの追加が許可されているかどうかを確認できます。

+0

これを徹底的に説明していただき、ありがとうございます。 – Zhro

2

あなたはIConfigにジェネリック型パラメータを追加することによって、あなたの目標を達成することができます

public class Test { 
    public interface IConfigUser { 
    } 

    public interface IConfig<T extends IConfigUser> { 
     public List<T> getUserList(); 
     public void setUserList(List<T> list); 
    } 


    public class ConfigUser implements IConfigUser { 
    } 

    public class Config implements IConfig<ConfigUser> { 
     @Override 
     public List<ConfigUser> getUserList() { 
     return null; 
     } 

     @Override 
     public void setUserList(List<ConfigUser> list) 
     { 
     } 
    } 
} 
2

あなたはにオーバーライドで、より具体的な型を返すことができますが、ことを必要とすることはできませんより具体的なタイプのを受け入れます。ジェネリックスを取り除き、Stringを返すメソッドでObjectを返すメソッドをオーバーライドできますが、Stringパラメータを受け入れるメソッドでObjectパラメータを受け入れるメソッドをオーバーライドすることはできません。

これはすべて、発信者に対応するためのものです。考えてみましょう:

IConfig config = new Config();  
List<SomeOtherConfigUser> list = new ArrayList<SomeOtherConfigUser>(); 
list.add(new SomeOtherConfigUser()); 
config.setUserList(list); 

おっと - あなたのConfig.setUserListSomeOtherConfigUserConfigUserなるためにあらゆる要素がない期待しています。

関連する問題