Skip to content
Theory · Inheritance and interfaces · lesson 6 of 10

Abstract classes

Try buying "a vehicle in general." A dealer will offer you a car, a truck or a bicycle, but not a vehicle of no kind at all. "Vehicle" is a general idea: it describes what every kind has, but it does not stand in the fleet on its own.

Every vehicle has, say, a top speed. But you cannot name it for "a vehicle in general": a car has one, a bicycle another. An ordinary class Vehicle would force you to put some guessed number into the method MaxSpeed. You need a way to say: "every kind has this method, and each kind writes its body."

C#
Vehicle car = new Car("Lada");
Console.WriteLine(car.Describe()); // Lada: 180 km/h

abstract class Vehicle
{
    public string Name;
    protected Vehicle(string name) { Name = name; }
    public abstract int MaxSpeed();
    public string Describe() => $"{Name}: {MaxSpeed()} km/h";
}
class Car : Vehicle
{
    public Car(string name) : base(name) { }
    public override int MaxSpeed() => 180;
}

Let's walk through it line by line:

  1. abstract class Vehicle declares a class whose objects cannot be created: it exists only to be a base class.
  2. public abstract int MaxSpeed(); is a method with no body: a semicolon stands where the braces would be.
  3. Describe is an ordinary method with a body. It calls MaxSpeed without knowing what kind of vehicle it will be.
  4. Car overrides MaxSpeed with override and returns 180.
  5. car.Describe() prints Lada: 180 km/h: the method from Vehicle called the version of MaxSpeed from Car.

An abstract class

An abstract class is a class marked with the abstract modifier, whose objects cannot be created. The line var v = new Vehicle("Cart"); does not compile:

TEXT
error CS0144: Cannot create an instance of the abstract type or interface 'Vehicle'

A variable of an abstract type, however, is allowed: Vehicle car = new Car("Lada"); leads to a Car object.

Otherwise, an abstract class works like an ordinary one: it can have fields, constructors and methods with bodies. The Vehicle constructor is declared protected: only the constructors of derived classes call it, through : base(name), and nobody else needs to.

An abstract method

An abstract method is a method marked abstract and without a body. It declares, "every derived class has this method," and leaves the body to them. Three rules apply to it:

  • an abstract method can exist only in an abstract class;
  • it is virtual by itself: it is overridden with override, although it has no word virtual;
  • a derived class that is not abstract must override it, unless a class above it in the inheritance chain already has.

The second kind of vehicle is one more class with its own version of MaxSpeed:

C#
Vehicle bike = new Bike("BMX");
Console.WriteLine(bike.Describe()); // BMX: 25 km/h

class Bike : Vehicle
{
    public Bike(string name) : base(name) { }
    public override int MaxSpeed() => 25;
}

This fragment continues the first program: add the statements after its statements, and the class Bike at the end of the file. The method Describe is written once, yet it works for each kind with its own speed.

This is how an abstract class splits the work: it does the shared part itself and leaves what differs between the kinds to the derived classes. This approach is called abstraction: the code works with the general idea of "a vehicle" and does not depend on the details of each kind.

Here the analogy is off. You will not meet "a vehicle in general" in the fleet. A variable of type Vehicle, however, does exist in the program, and it always leads to an object of a specific kind.

abstract or virtual

Interviewers often ask you to compare an abstract method with a virtual one. Both can be overridden with override, and they differ like this:

  • a virtual method has a body, and a derived class may override it or leave it as it is;
  • an abstract method has no body, and a derived class that is not abstract does not compile until the method is overridden.

Common mistake

A new kind of vehicle was declared, and the abstract method was not overridden:

C#
class Truck : Vehicle // ✗
{
    public Truck(string name) : base(name) { }
}
TEXT
error CS0534: 'Truck' does not implement inherited abstract member 'Vehicle.MaxSpeed()'

The program does not compile. A Truck object would have no version of MaxSpeed, and the call MaxSpeed() in Describe would have nothing to run. That is why the compiler requires a body. Add the line public override int MaxSpeed() => 90; to Truck.

Key points

  • You cannot create an object of an abstract class (CS0144), but a variable of its type can lead to an object of a derived class.
  • An abstract method has no body; a non-abstract derived class does not compile until the method is overridden with override.
  • An abstract class can have fields, constructors and ordinary methods with bodies.
  • A virtual method may be overridden, while an abstract method must be.