Given the following example, why am I able to override the return type List<? extends IConfigUser>
as List<ConfigUser>
in getUserList()
but cannot do the same for the parameter of setUserList()
?
Isn't ConfigUser
considered a supertype of IConfigUser
in this case?
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)
{
}
}
}
You can return a more specific type in an override, but you can't require that you accept a more specific type. Get rid of the generics, and you can override a method returning Object
with a method returning String
, but you can't override a method accepting an Object
parameter with a method accepting a String
parameter.
All of this is so that callers are compatible. Consider:
IConfig config = new Config();
List<SomeOtherConfigUser> list = new ArrayList<SomeOtherConfigUser>();
list.add(new SomeOtherConfigUser());
config.setUserList(list);
Oops - your Config.setUserList
is expecting every element to be a ConfigUser
, not a SomeOtherConfigUser
.
See more on this question at Stackoverflow