接口继承 - 更改方法参数

时间:2014-12-09 08:20:06

标签: java oop inheritance interface

我很难理解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
}

有人可以解释为什么第一种方法有效,而第二种方法没有?

4 个答案:

答案 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)

这是函数覆盖的工作方式。

  1. 功能参数必须完全相同。

  2. 返回类型可以不同,但必须相关。

  3. 因此,在您的情况下,getModel很好,因为返回类型(BaseModel)与Model相关,但setModel无效,因为参数类型不同

答案 3 :(得分:2)

方法名称和参数类型在Java中生成方法签名,而不是返回类型。覆盖方法时,方法的签名应该相同 如果您更改签名,它将会重载而不是覆盖 - 如果您删除了@Override注释,它将会工作。