This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

C# Programming
.NET 1.1+

C# Inheritance

The eighteenth part of the C# Object-Oriented Programming tutorial begins the discussion of the use of inheritance. This is a powerful object-oriented concept that permits the creation of hierarchical groups of classes that share common functionality.

Protected Scope

Earlier in this tutorial we examined the use of public and private access modifiers to modify the scope of variables, methods, properties, etc. To recap, items within classes that have a public scope are visible outside of the class. Items marked as private are visible only within the scope of a class.

Another access modifier exists for use in inheritance hierarchies. This is the protected access modifier. A protected item is generally as visible as if it were private except for one special case. If an item in a base class is declared as protected, it is visible to its subclasses.

To demonstrate this, add the following property to the MotorVehicle class. The property calculates the fuel efficiency of the motor vehicle in miles per gallon, with the calculation base upon the current speed of the vehicle.

public int Mpg
        if (_speed == 0)
            return 0;
        else if (_speed < 20)
            return 50;
        else if (_speed < 50)
            return 40;
            return 35;

If you attempt to compile the application you will receive three compiler errors. Each indicates that the "_speed" variable is inaccessible due to its protection level. In other words, because "_speed" is declared in the Vehicle class as a private variable it cannot be used within the MotorVehicle subclass. However, if you modify the variable in the Vehicle class to be protected, it will be visible to the subclass and the program will compile correctly.

protected int _speed;           // Miles per hour

Multi-Level Hierarchies

The benefits of inheritance are not limited to the two-level hierarchies that have been shown in the above examples. It is possible to add further subclasses to create multi-level inheritance. This allows each child to add more specialised functionality whilst retaining the members of its parents, grandparents and so on.

In the case of the vehicles example, it would be likely that you would want separate classes for cars, motorcycles and buses. Each of these could inherit from the MotorVehicle class for a three-level hierarchy. A class for lorries with a property for their load capacity could be as follows:

class Lorry : MotorVehicle
    private int _capacity;      // Cubic metres

    public int Capacity
        get { return _capacity; }
        set { _capacity = value; }

As the Lorry class is derived from the MotorVehicle class, which in turn is a subclass of Vehicle, the functionality from all three of these classes would be available to any Lorry object.

Preventing Inheritance

In some situations you may want to prevent inheritance. For example, you may create a class for use by other programmers where the class contains security functionality that must not be modified. To indicate that a class may not be inherited you can prefix the class definition with the sealed keyword.

To demonstrate, modify the declaration of the Vehicle class as follows:

sealed class Vehicle

The use of the sealed keyword prevents the MotorVehicle and Bicycle classes from inheriting functionality from Vehicle, so the application no longer compiles. You also receive a compiler warning highlighting that the "_speed" variable is protected. This warning appears because including a protected variable in a sealed class suggests that a mistake has been made. In any case, a protected variable may not be inherited from a sealed class.

A Final Note on Events and Inheritance

Events that are declared in a base class are still available for subscription from derived classes. However, the derived class is not able to raise an event defined in the base class. In the earlier article describing events, it was suggested that a centralised method be created that raises an event and that this method be marked as virtual. You can now see the benefit of this approach, as the derived class is able to call this method and indirectly raise the event. Alternatively, the subclass can override the event-calling method to change how events are raised.

15 March 2008