Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it required to have override keyword in front of abstract methods when we implement them in a child class?

Tags:

c#

When we create a class that inherits from an abstract class and when we implement the inherited abstract class why do we have to use the override keyword?

public abstract class Person
{
    public Person()
    {

    }

    protected virtual void Greet()
    {
        // code
    }

    protected abstract void SayHello();
}

public class Employee : Person
{
    protected override void SayHello() // Why is override keyword necessary here?
    {
        throw new NotImplementedException();
    }

    protected override void Greet()
    {
        base.Greet();
    }
}

Since the method is declared abstract in its parent class it doesn't have any implementation in the parent class, so why is the keyword override necessary here?

like image 975
psj01 Avatar asked Dec 20 '19 16:12

psj01


2 Answers

When we create a class that inherits from an abstract class and when we implement the inherited abstract class why do we have to use the override keyword?

"Why?" questions like this can be hard to answer because they are vague. I'm going to assume that your question is "what arguments could be made during language design to argue for the position that the override keyword is required?"

Let's start by taking a step back. In some languages, say, Java, methods are virtual by default and overridden automatically. The designers of C# were aware of this and considered it to be a minor flaw in Java. C# is not "Java with the stupid parts taken out" as some have said, but the designers of C# were keen to learn from the problematic design points of C, C++ and Java, and not replicate them in C#.

The C# designers considered overriding to be a possible source of bugs; after all, it is a way to change the behaviour of existing, tested code, and that is dangerous. Overriding is not something that should be done casually or by accident; it should be designed by someone thinking hard about it. That's why methods are not virtual by default, and why you are required to say that you are overriding a method.

That's the basic reasoning. We can now go into some more advanced reasoning.

StriplingWarrior's answer gives a good first cut at making a more advanced argument. The author of the derived class may be uninformed about the base class, may be intending to make a new method, and we should not allow the user to override by mistake.

Though this point is reasonable, there are a number of counterarguments, such as:

  • The author of a derived class has a responsibility to know everything about the base class! They are re-using that code, and they should do the due diligence to understand that code thoroughly before re-using it.
  • In your particular scenario the virtual method is abstract; it would be an error to not override it, and so it is unlikely that the author would be creating an implementation by accident.

Let's then make an even more advanced argument on this point. Under what circumstances can the author of a derived class be excused for not knowing what the base class does? Well, consider this scenario:

  • The base class author makes an abstract base class B.
  • The derived class author, on a different team, makes a derived class D with method M.
  • The base class author realizes that teams which extend base class B will always need to supply a method M, so the base class author adds abstract method M.
  • When class D is recompiled, what happens?

What we want to happen is the author of D is informed that something relevant has changed. The relevant thing that has changed is that M is now a requirement and that their implementation must be overloaded. D.M might need to change its behaviour once we know that it could be called from the base class. The correct thing to do is not to silently say "oh, D.M exists and extends B.M". The correct thing for the compiler to do is fail, and say "hey, author of D, check out this assumption of yours which is no longer valid and fix your code if necessary".

In your example, suppose the override was optional on SayHello because it is overriding an abstract method. There are two possibilities: (1) the author of the code intends to override an abstract method, or (2) the overriding method is overriding by accident because someone else changed the base class, and the code is now wrong in some subtle way. We cannot tell these possibilities apart if override is optional.

But if override is required then we can tell apart three scenarios. If there is a possible mistake in the code then override is missing. If it is intentionally overriding then override is present. And if it is intentionally not overriding then new is present. C#'s design enables us to make these subtle distinctions.

Remember compiler error reporting requires reading the mind of the developer; the compiler must deduce from wrong code what correct code the author likely had in mind, and give an error that points them in the correct direction. The more clues we can make the developer leave in the code about what they were thinking, the better a job the compiler can do in reporting errors and therefore the faster you can find and fix your bugs.

But more generally, C# was designed for a world in which code changes. A great many features of C# which appear "odd" are in fact there because they inform the developer when an assumption that used to be valid has become invalid because a base class changed. This class of bugs is called "brittle base class failures", and C# has a number of interesting mitigations for this failure class.

like image 138
Eric Lippert Avatar answered Sep 28 '22 05:09

Eric Lippert


It's to specify whether you're trying to override another method in the parent class or create a new implementation unique to this level of the class hierarchy. It's conceivable that a programmer might not be aware of the existence of a method in a parent class with exactly the same signature as the one they create in their class, which could lead to some nasty surprises.

While it's true that an abstract method must be overridden in a non-abstract child class, the crafters of C# probably felt it's still better to be explicit about what you're trying to do.

like image 36
StriplingWarrior Avatar answered Sep 28 '22 05:09

StriplingWarrior