Start learning free

LESSON 185 OF 347 · OBJECT-ORIENTED PROGRAMMING

Inheritance in C#: Derived Classes and the base Keyword

Lesson Read the full explanation

TL ; DR:

A child class can inherit from a parent class — it gets all the parent's fields and methods for free, and can add its own. This lets you reuse code instead of copy-pasting it.


class Puppy : Dog {
    public Puppy(string name) : base(name) { }
    public void Whine() { Console.WriteLine("whimper"); }
}


Full lesson:

Inheritance is one of the four classic OOP pillars (along with encapsulation, polymorphism, and abstraction). The idea is simple: most real-world things are kinds of other things — a Puppy is a Dog, a Car is a Vehicle, a Manager is an Employee. When you model that "is-a" relationship in code, the child class gets the parent's data and behavior automatically.

What gets inherited?

  • Fields — the Puppy has a name field even though we only declared it on Dog.
  • Methods — the Puppy can call bark() even though we only defined it on Dog.
  • The contract — anywhere code expects a Dog, you can pass a Puppy (we'll see this when we cover polymorphism).

What you still write

  • The constructor usually has to forward arguments up to the parent's constructor (because the parent's fields need initializing).
  • Any new methods or new fields specific to the child.

Your task

Below the Dog class, create a Puppy class that inherits from Dog and adds one new method, whine(), that prints "whimper". The harness creates a Puppy named "Buddy", calls its inherited bark(), and then its new whine().

Expected output:

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

    C# · OBJECT-ORIENTED PROGRAMMING

    Inheritance in C#, explained

    What inheritance is

    Inheritance lets one class build on another. The new class, called the derived or child class, automatically gets the members of an existing base or parent class, and then adds members of its own. You write the shared fields and methods once, in the base class, instead of copying them into every class that needs them.

    Inheritance models an "is-a" relationship. A puppy is a dog, so a Puppy class can reasonably inherit from Dog: everything a dog has and does, a puppy has and does too, plus a few extras. A quick test before you reach for inheritance is to say the sentence out loud. "A puppy is a dog" makes sense. "A dog is a collar" doesn't, so if a dog needs a collar, give Dog a field of type Collar instead.

    Inheritance is one of the classic pillars of object-oriented programming, alongside encapsulation, polymorphism and abstraction, and the later lessons in this chapter build on it.

    The syntax

    In C#, a class names its base class after a colon. Here is the lesson's Dog class and a Puppy that derives from it:

    class Dog {
        public string name;
        public Dog(string name) { this.name = name; }
        public void Bark() {
            Console.WriteLine("Woof! I am " + name);
        }
    }
    
    class Puppy : Dog {
        public Puppy(string name) : base(name) { }
        public void Whine() {
            Console.WriteLine("whimper");
        }
    }
    

    Three things are happening in Puppy:

    • class Puppy : Dog declares that Puppy derives from Dog.
    • public Puppy(string name) : base(name) { } is the constructor. The : base(name) part calls Dog's constructor with the same name, so the inherited name field gets set. The body is empty because there is nothing else to do.
    • Whine is new behaviour that only puppies have.

    A Puppy object can now use both its own method and the inherited ones:

    Puppy buddy = new Puppy("Buddy");
    buddy.Bark();                   // Woof! I am Buddy
    buddy.Whine();                  // whimper
    Console.WriteLine(buddy.name);  // Buddy
    

    What a derived class can use

    The access modifiers on the base class decide what the derived class can touch:

    • public members, like name and Bark, work in Puppy as if Puppy had declared them.
    • protected members are visible inside derived classes but not to outside code.
    • private members still exist inside every Puppy object, but code in Puppy can't refer to them by name.
    • Constructors are not inherited. Each class declares its own and passes what the base class needs through base(...).

    The base constructor runs first

    Creating a derived object always runs the base class's constructor before the derived constructor's body. When a constructor has no : base(...), C# calls the base class's parameterless constructor for you:

    class Animal {
        public Animal() {
            Console.WriteLine("Animal constructor");
        }
    }
    
    class Cat : Animal {
        public Cat() {
            Console.WriteLine("Cat constructor");
        }
    }
    
    // new Cat() prints:
    // Animal constructor
    // Cat constructor
    

    A derived object is also a base object

    Because a puppy is a dog, a Puppy can go anywhere a Dog is expected:

    Dog pet = new Puppy("Rex");
    pet.Bark();      // Woof! I am Rex
    // pet.Whine();  // compile error: the variable's type is Dog, and Dog has no Whine
    

    The variable's declared type decides which members you can call. This idea is the starting point for polymorphism.

    Two more rules complete the picture. A C# class can have only one base class, although it may also implement any number of interfaces. And every class ultimately derives from object, which is why methods like ToString() exist on everything.

    Common mistakes and gotchas

    • Leaving out : base(name). Without it, C# tries to call Dog() with no arguments. Dog only has a constructor that takes a name, so the code doesn't compile. Omitting the Puppy constructor entirely fails the same way, because the constructor C# generates also calls Dog().
    • Forgetting public. Class members are private by default. If you write void Whine(), the call buddy.Whine() from another class is rejected.
    • Using a private base member. Code in a derived class can't read the base class's private fields. Mark them protected if derived classes should see them.
    • Accidentally hiding a method. Declaring public void Bark() again in Puppy hides the inherited one, and the compiler warns about it. Replacing behaviour properly uses virtual and override, which method overriding covers.
    • Wrong capitalisation. C# is case-sensitive, and methods are conventionally PascalCase. The lesson calls Bark and Whine, so a method named whine doesn't match, and buddy.Whine() fails to compile.
    • Inheriting just to reuse code. If the "is-a" sentence sounds wrong, use a field instead. Inheritance ties the two classes tightly: every change to the base class reaches the derived one.

    The exercise, step by step

    The lesson gives you Dog and a Solution class whose MainFunction creates a Puppy named "Buddy" and calls Bark() and Whine() on it. Your job is to write Puppy between them.

    1. Declare the class and its constructor. Write class Puppy : Dog so Puppy inherits the name field and the Bark method. Give it a public constructor that takes a string name and forwards it with : base(name), since Dog's field still has to be set by Dog's constructor.
    2. Add the new behaviour. Inside Puppy, add public void Whine() that prints "whimper" with Console.WriteLine. Bark is already inherited, so this is the only method you write.

    When the program runs, new Puppy("Buddy") calls the Puppy constructor, which passes "Buddy" up to Dog's constructor to set name. The inherited Bark() then prints Woof! I am Buddy, and Whine() prints whimper, matching the expected output line for line.

    Key takeaways

    • class Child : Parent makes Child inherit Parent's members.
    • Use inheritance for "is-a" relationships, and a field for "has-a" ones.
    • Constructors aren't inherited; forward arguments with : base(...), and the base constructor runs first.
    • Public and protected members are usable in the derived class; private ones are not.
    • A derived object can be stored in a variable of the base type, but only the base type's members are callable through it.
    • C# allows one base class per class, and every class derives from object.
    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