简体   繁体   中英

Why can one change the return type of an abstract method in java?

Why is changing the return type of an abstract method in a child class allowed?

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();
    }
}

whereas changing the parameter type is not allowed:

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) {
    }
}

Because, overriden methods are allowed to have co-variant returns from java 1.5+ version .

Also to add when you change the parameter type in your concrete class you are basically declaring a completely new method which is different from your abstract method defined in your abstract class. Remember you need(forced by the compiler) to implement/override those abstarct methods in your concrete class which extends your abstract class.

Simply put here are the Rules for Overriden methods in java:

  • Overridden method and argument list shall exactly be the same
  • Return type shall be the subtype(in case of co-variant returns) that is being declared in original method that is overridden in superclass, or it shall be the same.
  • Restriction is not more in case of access level as compared to access level of the overridden method. Eg, when superclass is considerd to be public, in that case overriding method present in the subclass would not be public or private. But access level might not be much restrictive in comparison with access level of overridden method.
  • If instance methods are inherited, by subclass, in that case only they might be overridden.
  • Method which has been declared final might not get overridden.

In your question you mix up two aspects: using a subtype in the overriding method and using a completely unrelated type , and a primitive at that, in the method arguments.

You can never, in no context, change an int from a overridden method into a float in the overriding method. The only special case that is allowed is return type covariance. Theoretically, the argument types could be contravariant, but that would make a mess out of method overload resolution, which is already very complex.

Overridden methods should have Same number of method parameters and their type should be same. But they are allowed to have covariant returns

To state this differently: A method that returns a subtype of the one required by the abstract method still fulfills the contract. While a method that takes a float does not fulfill the contract that the method takes an int.

Covariant return, means that when one overrides a method, the return type of the overridden method is allowed to be a subtype of the overridden method's return type. To clarify this with an example, a common case is Object.clone() - which is declared to return a type of Object. You could override this in your own class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM