What overriding means
A derived class inherits the methods of its base class. Overriding is what you do when the derived class wants to change one of them. A Puppy is a Dog, but it sounds different: it says "Yip!" where a dog says "Woof!". Instead of inventing a new method name, Puppy replaces the behaviour of Bark. Code that calls Bark doesn't need to know which kind of dog it is holding.
virtual and override
In C#, methods can't be overridden by default. Two keywords work as a pair:
- The base class marks the method
virtual, which says "derived classes may replace this". - The derived class marks its replacement
override, which says "this is the replacement".
class Dog {
public string name;
public Dog(string name) { this.name = name; }
public virtual void Bark() {
Console.WriteLine("Woof! I am " + name);
}
}
class Puppy : Dog {
public Puppy(string name) : base(name) { }
public override void Bark() {
Console.WriteLine("Yip! I am " + name);
}
}
The override must have the same name, parameters and accessibility as the method it replaces, and a compatible return type. The compiler checks all of that. This is stricter than some languages, and it catches typos: an override with no matching virtual method in the base class is an error.
The object decides
When you call an overridden method, C# runs the version that belongs to the object's actual class, even if the variable's declared type is the base class:
Dog d = new Puppy("Buddy");
d.Bark(); // Yip! I am Buddy
The variable is a Dog, but the object is a Puppy, so Puppy.Bark runs. This is the basis of polymorphism, the topic of the next lesson.
Extending instead of replacing
An override can still use the base version. The keyword base reaches the parent's implementation:
class LoudDog : Dog {
public LoudDog(string name) : base(name) { }
public override void Bark() {
base.Bark();
Console.WriteLine("(and louder)");
}
}
Calling Bark on a LoudDog named "L" prints Woof! I am L and then (and louder). This is handy when the derived class adds to the behaviour rather than replacing it.
Common mistakes
- Forgetting
virtualin the base class. Thenoverridein the derived class fails with an error that the member can't be overridden because it is not marked virtual, abstract or override. - Forgetting
overridein the derived class. The code compiles, but with a warning that the new method hides the inherited one. The hiding method is a different method, not a replacement. A call through aDogvariable still runsDog.Bark, so the object's real class no longer decides. If hiding is what you want, say so with thenewmodifier; most of the timeoverrideis the right choice. - Changing the signature. A method with different parameters is an overload, not an override.
- Changing the accessibility. If the base method is
public, the override can't beprivateorprotected. - Using lowercase names. The lesson's method is
Bark. A method calledbarkis a different method, and C# conventions use PascalCase. - Assuming Java rules. In Java, every non-final method can be overridden. In C# you must opt in with
virtualin the base class.
The exercise, step by step
The lesson gives you Dog, whose Bark is virtual, and a Puppy class that currently has only a constructor. MainFunction creates a Puppy named "Buddy" and calls Bark. The expected output is:
Yip! I am Buddy
- Declare an empty override inside
Puppy:public override void Bark() { }. It matches the base method in name, parameters, return type and accessibility. - Fill in the body. Print
"Yip! I am "followed byname. The field is inherited fromDog, so you use it directly.
class Dog {
public string name;
public Dog(string name) { this.name = name; }
public virtual void Bark() {
Console.WriteLine("Woof! I am " + name);
}
}
class Puppy : Dog {
public Puppy(string name) : base(name) { }
public override void Bark() {
Console.WriteLine("Yip! I am " + name);
}
}
class Solution {
public void MainFunction() {
Puppy buddy = new Puppy("Buddy");
buddy.Bark();
}
}
Key takeaways
- The base method is marked
virtual; the derived method is markedoverride. - An override has the same name, parameters and accessibility as the original.
- The object's real class decides which version runs.
base.Method()calls the parent's version from inside an override.- Leaving out
overridehides the method instead of replacing it.