Last modified on 5 September 2014, at 00:56

C# Programming/Inheritance

InheritanceEdit

Inheritance is the ability to create a class from another class, the "parent" class, extending the functionality and state of the parent in the derived, or "child" class. It allows derived classes to overload methods from their parent class.

Inheritance is one of the pillars of object-orientation. It is the mechanism of designing one class from another and is one of the ideas for code reusability, supporting the concept of hierarchical classification. C# programs consist of classes, where new classes can either be created from scratch or by using some or all properties of an existing class.

Another feature related to inheritance and reusability of code is polymorphism, which permits the same method name to be used for different operations on different data types. Thus, C# supports code reusability by both features.

Important characteristics of inheritance include:

  1. A derived class extends its base class. That is, it contains the methods and data of its parent class, and it can also contain its own data members and methods.
  2. The derived class cannot change the definition of an inherited member.
  3. Constructors and destructors are not inherited. All other members of the base class are inherited.
  4. The accessibility of a member in the derived class depends upon its declared accessibility in the base class.
  5. A derived class can override an inherited member.

An example of inheritance:

using System;
using System.Text;
 
namespace ContainmentInheritance
{
    class Room
    {
        public int length;
        public int width;
        public int height;
        public string name;
 
        public Room(int l, int w, int h)
        {
            length = l;
            width = w;
            height = h;
        }
    }
 
    class Home
    {
        int numberOfRooms;
        int plotSize;
        string locality;
 
        // create an object of class Room inside class Home
        Room studyRoom = new Room(10, 12, 12);
 
        public Home()
        {
            numberOfRooms = 1;
            plotSize = 1000;
            locality = "Versova";
            name = "study room";
        }
 
        public void Display()
        {
            Console.WriteLine("MyHome has {0} rooms", numberOfRooms);
            Console.WriteLine("Plot size is {0}", plotSize);
            Console.WriteLine("Locality is {0}", locality);
 
            int area = studyRoom.length*studyRoom.width;
            Console.WriteLine("Area of the {0} room is {1}", name, area);
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Home myhome = new Home();
            myhome.Display();
 
            Console.ReadLine();
        }
    }
}

Subtyping InheritanceEdit

The code sample below shows two classes, Employee and Executive. Employee has the methods GetPayCheck and Work.

We want the Executive class to have the same methods, but differently implemented and one extra method, AdministerEmployee.

Below is the creation of the first class to be derived from.

public class Employee
{
    // We declare one method virtual so that the Executive class can
    // override it.
    public virtual void GetPayCheck()
    {
        // Get paycheck logic here.
    }
 
    //Employee's and Executives both work, so no virtual here needed.
    public void Work()
    {
        // Do work logic here.
    }
}

Now, we create an Executive class that will override the GetPayCheck method:

public class Executive : Employee
{
    // The override keyword indicates we want new logic behind the GetPayCheck method.
    public override void GetPayCheck()
    {
        // New getpaycheck logic here.
    }
 
    // The extra method is implemented.
    public void AdministerEmployee()
    {
        // Manage employee logic here
    }
}

You'll notice that there is no Work method in the Executive class, as it is inherited from Employee.

static void Main(string[] args)
{
    Employee emp = new Employee();
    Executive exec = new Executive();
 
    emp.Work();
    exec.Work();
    emp.GetPayCheck();
    exec.GetPayCheck();
    exec.AdministerEmployee();
}

Virtual MethodsEdit

If a base class contains a virtual method that it calls elsewhere and a derived class overrides that virtual method, the base class will actually call the derived class' method:

public class Resource : IDisposable
{
    private bool _isClosed = false;    // good programming practice initialise, although default
 
    protected virtual void Close()
    {
        Console.WriteLine("Base resource closer called!");
    }
 
    ~Resource()
    {
        Dispose();
    }
 
    public void Dispose()
    {
        if (!_isClosed)
        {
            Console.WriteLine("Disposing resource and calling the Close() method...");
            _isClosed = true;
            Close();
        }
    }
}
 
public class AnotherTypeOfResource : Resource
{
    protected override void Close()
    {
        Console.WriteLine("Another type of resource closer called!");
    }
}
 
public class VirtualMethodDemo
{
    public static void Main()
    {
        Resource res = new Resource();
        AnotherTypeOfResource res2 = new AnotherTypeOfResource();
 
        res.Dispose();  // Resource.Close() will be called.
        res2.Dispose(); // Even though Dispose() is part of the Resource class, 
                        // the Resource class will call AnotherTypeOfResource.Close()!
    }
}

ConstructorsEdit

A derived class does not automatically inherit the base class' constructors, and it cannot be instantiated unless it provides its own. A derived class must call one of its base class' constructors by using the base keyword:

public class MyBaseClass
{
    public MyBaseClass(string text)
    {
        ...
    }
}
 
public class MyDerivedClass : MyBaseClass
{
    public MyDerivedClass(int number)
        : base(number.ToString())
    { }
 
    public MyDerivedClass(string text) // even though this is exactly the same as MyBaseClass'  
    // only constructor, this is still necessary as constructors are not inherited.
        : base(text)
    { }
}

Inheritance keywordsEdit

The way C# inherits from another class syntactically is by using the : operator.

Example:

public class Executive : Employee

To indicate a method that can be overridden, you mark the method with virtual.

public virtual void Write(string text)
{
    System.Console.WriteLine("Text:{0}", text);
}

To override a method, use the override keyword:

public override void Write(string  text)
{
    System.Console.WriteLine(text);
}

A missing new or override keyword for a derived method may result in errors or warnings during compilation.:[1] Here an example:

abstract class ShapesA
{
    abstract public int Area(); // abstract!
}
 
class Square : ShapesA
{
    int x, y;
 
    public int Area() // Error: missing 'override' or 'new'
    {
        return x * y;
    }
} 
 
class Shapes
{
    virtual public int Area() { return 0; } // it is virtual now!
}
 
class Square : Shapes
{
    int x, y;
 
    public int Area() // no explicit 'override' or 'new' required
    { return x * y; }
}

The Square class method Area() will result in a compilation error, if it is derived from the ShapesA class:

error CS0534: 'ConsoleApplication3.Square' does not implement inherited abstract member
'ConsoleApplication3.Shapes.Area()'

The same method will result in a compilation warning, if derived from the normal Shapes class:

warning CS0114: 'ConsoleApplication3.Square.Area()' hides inherited member 'ConsoleApplication3.Shapes.Area()'.
To make the current member override that implementation, add the override keyword. Otherwise add the new
keyword.

ReferencesEdit

  1. Greg Beech (2010-03-09). "C# design: Why is new/override required on abstract methods but not on virtual methods? / Answer". http://efreedom.com/: eFreedom. http://efreedom.com/Question/1-3634529/CSharp-Design-New-Override-Required-Abstract-Methods-Virtual-Methods. Retrieved 2011-08-11. "Using either the C# 3.0 compiler as shipped in .NET 3.5 SP1, or the C# 4.0 compiler as shipped in .NET 4.0, I get the following error for your first example: [...] And the following warning for the second one: [...] In the first case it's an error because you aren't actually overriding the base method, which means there is no implementation for the abstract method in a concrete class. In the second case it's a warning because the code is technically correct, but the compiler suspects that it isn't what you meant. This is one of the reasons it's generally a good idea to enable the "treat warnings as errors" compilation setting."