Start learning free

LESSON 186 OF 347 · OBJECT-ORIENTED PROGRAMMING

Method Overriding in C#: virtual, override and base

Lesson Read the full explanation

TL ; DR:

When a child class defines a method with the same name as the parent's, the child's version overrides the parent's. Different objects can give the same method name different behavior.


class Dog {
    public virtual void Bark() { Console.WriteLine("Woof!"); }
}
class Puppy : Dog {
    public override void Bark() { Console.WriteLine("Yip!"); }
}


Full lesson:

You've seen that a child class inherits the parent's methods. Overriding is what happens when the child wants to change one of those inherited methods.

Why override?

Subclasses are usually special cases of the parent. A Puppy is a Dog, but it sounds different — "Yip!" instead of "Woof!". Instead of inventing a new method name, you redefine bark() on the Puppy. Callers don't need to know which subclass they're holding — they just call bark() and the right version runs.

How it works in each language

  • C# — the parent method must be marked virtual, the child marks its replacement override. The compiler enforces this pairing.
  • Java — every non-final method is virtual by default; the @Override annotation is optional but tells the compiler to verify the signature matches.
  • Python — defining a method with the same name in the child class replaces the parent's. No keyword required.
  • JavaScript — same as Python: define the method again on the child class and it wins.
  • C++ — the parent method must be virtual; override on the child is optional but compiler-checked.

Your task

The Dog class already defines bark. Inside the Puppy subclass, override bark so it prints "Yip! I am " followed by the puppy's name. The harness creates a Puppy named "Buddy" and calls bark() on it.

Expected output:

Yip! I am Buddy
STEP 1 OF 2
    Ctrl + Enter to check

    C# · OBJECT-ORIENTED PROGRAMMING

    Method Overriding in C#, explained

    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 virtual in the base class. Then override in the derived class fails with an error that the member can't be overridden because it is not marked virtual, abstract or override.
    • Forgetting override in 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 a Dog variable still runs Dog.Bark, so the object's real class no longer decides. If hiding is what you want, say so with the new modifier; most of the time override is 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 be private or protected.
    • Using lowercase names. The lesson's method is Bark. A method called bark is 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 virtual in 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
    
    1. Declare an empty override inside Puppy: public override void Bark() { }. It matches the base method in name, parameters, return type and accessibility.
    2. Fill in the body. Print "Yip! I am " followed by name. The field is inherited from Dog, 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 marked override.
    • 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 override hides the method instead of replacing it.
    Keep going with C#About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free