[英]Why can't object of nested class be used as a parameter of supertype constructor?
[英]Why is this class not considered a supertype as a parameter?
給定以下示例,為什么我可以覆蓋返回類型List<? extends IConfigUser>
List<? extends IConfigUser>
為getUserList()
List<ConfigUser>
,但不能對setUserList()
的參數進行相同的設置嗎?
在這種情況下, IConfigUser
是否不ConfigUser
視為ConfigUser
的超類型?
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)
{
}
}
}
您可以通過向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)
{
}
}
}
您可以在覆蓋中返回更具體的類型,但不能要求您接受更具體的類型。 擺脫泛型,可以用返回String
的方法重寫返回Object
的方法,但是不能用接受String
參數的方法重寫接受Object
參數的方法。
所有這些都是為了使呼叫者兼容。 考慮:
IConfig config = new Config();
List<SomeOtherConfigUser> list = new ArrayList<SomeOtherConfigUser>();
list.add(new SomeOtherConfigUser());
config.setUserList(list);
糟糕-您的Config.setUserList
期望每個元素都是ConfigUser
,而不是SomeOtherConfigUser
。
由於協方差,您可以返回(“ specialize”) getUserList()
)的返回類型,即,如果您在IConfig
引用上調用該方法,那么您將得到List<? extends IConfigUser>
List<? extends IConfigUser>
而List<ConfigUser>
是 List<? extends IConfigUser>
List<? extends IConfigUser>
以便滿足要求。
如果您在Config
參考上調用該信息,則該信息會更具體,但仍滿足基本要求。
使用setUserList(...)
的情況有所不同:它允許您傳遞List<? extends IConfigUser>
任何 “子類” List<? extends IConfigUser>
List<? extends IConfigUser>
,它可以是 List<ConfigUser>
但也可以是其他名稱,例如List<SomeConfigUser>
。
順便說一句,由於您不知道setUserList(List<ConfigUser> list)
中list
的具體泛型參數,因此編譯器也將只允許您從該列表中讀取內容,而從不添加該列表-出於與上述相同的原因:不知道您得到什么以及是否允許添加ConfigUser
,因為該列表僅允許添加SomeConfigUser
實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.