为什么可以在java中更改抽象方法的返回类型?

时间:2013-03-14 09:25:16

标签: java

为什么允许在子类中更改抽象方法的返回类型?

abstract class Animal {
    public abstract Animal assing(Animal a);
}

class Lizard extends Animal {
    @Override
    public Lizard assing(Animal a) {
        return new Lizard();
    }
}

class Chicken extends Animal {
    @Override
    public Chicken assing(Animal a) {
        return new Chicken();
    }
}

而不允许更改参数类型:

abstract class Animal {
    public abstract void foo(int x);
}

class Lizard extends Animal {
    // compiler error
    // the type Lizard must implement the inherited abstract method Animal.foo(int)
    public void foo(float x) {
    }
}

class Chicken extends Animal {
    @Override
    public void foo(int x) {
    }
}

5 个答案:

答案 0 :(得分:10)

因为overriden methods允许来自 java 1.5+版本co-variant returns

另外,当您在具体类中更改参数类型时,您基本上会声明一个全新的方法,该方法与您在抽象类中定义的抽象方法不同。记住你需要(由编译器强制)在你的具体类中实现/覆盖那些扩展你的抽象类的abstarct方法。

简单地说,这里是java中的 Overriden方法规则

  • 重写的方法和参数列表应完全相同
  • 返回类型应为在超类中重写的原始方法中声明的子类型(如果是共变量返回),或者它应该是相同的。
  • 与被覆盖方法的访问级别相比,访问级别的限制不多。例如,当考虑公共超类时,在这种情况下,子类中存在的重写方法将不是公共的或私有的。但是,与重写方法的访问级别相比,访问级别可能没有太大的限制。
  • 如果实例方法是由子类继承的,那么只有它们可能会被覆盖。
  • 声明为final的方法可能不会被覆盖。

答案 1 :(得分:1)

在你的问题中,你混淆了两个方面:在重写方法中使用子类型并在方法参数中使用完全不相关的类型和原语

在上下文方法中,您绝不能将int从重写方法更改为float。唯一允许的特殊情况是返回类型协方差。从理论上讲,参数类型可以是逆变的,但这会使方法重载解决方案变得混乱,这已经非常复杂了。

答案 2 :(得分:1)

重写方法应该具有相同数量的方法参数,并且它们的类型应该相同。但他们可以获得协变回报

答案 3 :(得分:0)

以不同的方式说明:返回抽象方法所需的子类型的方法仍然满足合同。虽然采用float的方法不符合该方法采用int的约定。

答案 4 :(得分:0)

协变返回,意味着当一个覆盖一个方法时,被覆盖方法的返回类型被允许是被覆盖方法的返回类型的子类型。 为了用一个例子来澄清这一点,一个常见的例子是Object.clone() - 它被声明为返回一种Object类型。你可以在你自己的班级中覆盖它。