Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Overriding an abstract method in subclass

Tags:

java

oop

I really should know this, but for some reason I don't understand the following.

My abstract class contains the following abstract method:

protected abstract RuleDTO createRowToBeCloned(RuleDTO ruleDTO);

I also have another class as follows:

EvaluationRuleDTO extends from RuleDTO

Then in a subclass of my abstract class I have the following implementation which is not allowed due to "must override or implement a supertype method":

protected EvaluationRuleDTO createRowToBeCloned(EvaluationRuleDTO ruleDTO) {

However, the following is allowed:

protected EvaluationRuleDTO createRowToBeCloned(RuleDTO ruleDTO) {

I realize this is probably a basic question but I am a little bemused. How come I can I can return a subclass of RuleDTO in the overridden method, but I can't pass in a subclass?

Thanks

like image 261
DJ180 Avatar asked Jul 19 '12 21:07

DJ180


People also ask

Can a subclass override an abstract class?

To implement features of an abstract class, we inherit subclasses from it and create objects of the subclass. A subclass must override all abstract methods of an abstract class.

Do subclasses inherit abstract methods?

Abstract classes cannot be instantiated, but they can be subclassed. When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, then the subclass must also be declared abstract .

What will happen if we do not override all abstract methods in subclass?

If you don't, a compile time error will be generated for each abstract method (that you don't override) saying “subclass_name is not abstract and does not override abstract method abstractmethod_name in classname”.

Can a subclass override private methods of an abstract class?

If a method of a class is private, you cannot access it outside the current class, not even from the child classes of it. But, incase of an abstract method, you cannot use it from the same class, you need to override it from subclass and use. Therefore, the abstract method cannot be private.


2 Answers

You're breaking the Liskov principle: everything a superclass can do, a subclass must be able to do. The superclass declares a method accepting any kind of RuleDTO. But in your subclass, you only accept instances of EvaluationRuleDTO. What would happen if you did the following?

RuleDTO rule = new EvaluationRuleDTO();
rule.createRowToBeCloned(new RuleDTO());

An EvaluationRuleDTO is a RuleDTO, so it must fulfill the contract defined by RuleDTO.

The method in the subclass may return an instance of EvaluationRuleDTO instead of a RuleDTO, though, because the contract is to return a RuleDTO, and EvaluationRuleDTO is a RuleDTO.

like image 112
JB Nizet Avatar answered Oct 11 '22 19:10

JB Nizet


Java allows return type covariance for overrides, so you can specify the return type of an override as a more-derived type. However, Java does not allow parameter type covariance for overrides.

The reason the former is safe is that the object you return will have, at minimum, the functionality of the less-derived type, so a client relying on that fact will still be able to utilize the returned object correctly.

That's not the case for the arguments, though. If it were legal, a user could call the abstract method and pass in a less-derived type (since that's the type declared on the abstract class,) but then your derived override might try to access the argument as a more-derived type (which it isn't) resulting in an error.

In theory, Java could have allowed parameter-type contra-variance, since that is type-safe: if the overriden method only expects a less-derived argument, you can't accidentally utilize a method or field that's not there. Unfortunately, that is not currently available.

like image 26
dlev Avatar answered Oct 11 '22 19:10

dlev