Source: Ch5_OOP.pdf

Inheritance

Base/derived relation, protected, virtual/override, base keyword, ToString override, and sealed.

Base and Derived Classes

Inheritance lets a derived class reuse and extend a base class. Use the colon (:) syntax. C# supports single direct inheritance for classes.

csharp
class Animal
{
    public string Name;
    public void Eat() => Console.WriteLine(Name + " is eating.");
}

class Dog : Animal
{
    public void Bark() => Console.WriteLine(Name + " says Woof!");
}

Dog d = new Dog();
d.Name = "Rex";
d.Eat();
d.Bark();

Output

Rex is eating.
Rex says Woof!

Base / Derived — Exercise 1

A derived class automatically inherits all public and protected members of its base class.

Fix the broken inheritance declaration

Hint

C# uses a colon (:) for inheritance, not the extends keyword.

How many direct base classes can a C# class inherit from?

Protected Members

protected members are accessible in the declaring class and in any class that inherits from it, but not from outside.

csharp
class Vehicle
{
    protected int Speed = 0;

    public void Accelerate(int amount) { Speed += amount; }
}

class Car : Vehicle
{
    public void ShowSpeed() => Console.WriteLine("Speed: " + Speed);
}

Car c = new Car();
c.Accelerate(60);
c.ShowSpeed();

Output

Speed: 60

Protected Members — Exercise 1

A protected field is accessible in subclasses but not from unrelated classes.

Fix the access to a protected field from outside

Hint

Add a public method that returns sound, since protected fields are not accessible outside the class hierarchy.

Where can a protected member be accessed?

Virtual and Override

Mark a base method virtual to allow derived classes to override it with override. The runtime calls the most derived version — this is runtime polymorphism.

csharp
class Shape
{
    public virtual void Display() => Console.WriteLine("Shape");
}

class Circle : Shape
{
    public override void Display() => Console.WriteLine("Circle");
}

class Square : Shape
{
    public override void Display() => Console.WriteLine("Square");
}

Shape s1 = new Circle();
Shape s2 = new Square();
s1.Display();
s2.Display();

Output

Circle
Square

Virtual / Override — Exercise 1

Forgetting virtual on the base method means derived classes cannot properly override it — the override keyword will cause a compile error.

Fix the missing virtual keyword

Hint

Add virtual to Animal.Speak() so that Cat can use override.

What keyword allows a derived class to replace a base class method at runtime?

Calling the Base Constructor with base()

Use : base(...) after the constructor signature to call a specific base class constructor. The base constructor always runs before the derived constructor body.

csharp
class Person
{
    public string Name;
    public Person(string name) { Name = name; }
}

class Student : Person
{
    public int StudentId;

    public Student(string name, int id) : base(name)
    {
        StudentId = id;
    }
}

Student s = new Student("Alice", 1001);
Console.WriteLine($"{s.Name} — ID {s.StudentId}");

Output

Alice — ID 1001

base() Practice — Exercise 1

If the base class has no parameterless constructor, the derived class must explicitly call one of the base constructors using : base(...).

Add the missing base constructor call

Hint

Add : base(name) after the constructor parameters to pass name to Animal's constructor.

When does the base constructor body run relative to the derived constructor?

Overriding ToString

Every class inherits ToString() from object. Override it to return a meaningful string representation, which is also used by Console.WriteLine().

csharp
class Book
{
    public string Title;
    public string Author;

    public Book(string title, string author)
    {
        Title = title;
        Author = author;
    }

    public override string ToString()
    {
        return $""{Title}" by {Author}";
    }
}

Book b = new Book("Clean Code", "Robert Martin");
Console.WriteLine(b);

Output

"Clean Code" by Robert Martin

Overriding ToString — Exercise 1

Without an override, Console.WriteLine(object) prints the fully qualified type name, which is rarely useful.

Override ToString to show meaningful output

Hint

Add public override string ToString() that returns a formatted string.

Which class does ToString() originally come from?

Sealed Classes

A sealed class cannot be used as a base class. It prevents further inheritance, which can improve performance and security. string is a well-known sealed type.

csharp
sealed class FinalClass
{
    public void Hello() => Console.WriteLine("I cannot be inherited.");
}

// This would be a compile error:
// class Child : FinalClass { }

FinalClass f = new FinalClass();
f.Hello();

Output

I cannot be inherited.

What does the sealed keyword do when applied to a class?