我很难理解java解释接口继承的方式,例如:
public interface Model {
Model getModel();
void setModel(Model model);
}
public class BaseModel implements Model {
@Override
public BaseModel getModel() { return null; } // works
@Override
public void setModel(BaseModel model) {} // compilation error, it wants Model instead of BaseModel
}
有人可以解释为什么第一种方法有效,而第二种方法没有?
答案 0 :(得分:5)
您的第一个方法的返回类型是covariant并且是允许的,并且返回类型不是方法签名的一部分因此允许
虽然方法的参数是签名的一部分,但必须严格遵循接口签名,因此在您的情况下会失败。
现在,由于您使用@Override
注释了方法,因此您尝试覆盖该方法,因此编译器会抱怨相同的方法。如果你只是删除那个并按照现有实现的方式实现方法,那么你将重载该方法。
答案 1 :(得分:4)
为了理解这一点,您应该问自己“我可以用BaseModel
替换Model
接口吗?”
当你专门化返回值时,这很好用。即使getModel()
返回BaseModel
,也可以始终将其分配给Model
变量。
Model model = myModel.getModel();
反之亦然:
SomeOtherModel other = ...;
myModel.setModel(other); // no problem
myBaseModel.setModel(other); // other is not a BaseModel!
如果setModel
要接受BaseModel
参数,则您将无法使用Model
的其他实现进行设置。因此,这是不允许的。
答案 2 :(得分:3)
这是函数覆盖的工作方式。
功能参数必须完全相同。
返回类型可以不同,但必须相关。
因此,在您的情况下,getModel
很好,因为返回类型(BaseModel
)与Model
相关,但setModel
无效,因为参数类型不同
答案 3 :(得分:2)
方法名称和参数类型在Java中生成方法签名,而不是返回类型。覆盖方法时,方法的签名应该相同 如果您更改签名,它将会重载而不是覆盖 - 如果您删除了@Override注释,它将会工作。