C# 11 Abstract Classes

In the preceding chapters, we have looked in detail at object-oriented programming in C# and also at the concept of class inheritance. In this lesson, we will look at the next area of object-oriented programming, the abstract class.

What is a C# abstract class?

In the examples we have looked at so far in this book, we have created classes that could be both instantiated as objects and used as a base class from which to derive classes. Often a base class is not intended to be instantiated and is provided solely to provide an outline or template for subclasses. Such a class is known as an abstract class. An abstract class cannot be instantiated as an object and is only provided to derive subclasses.

Abstract members

A C# abstract class contains abstract members, which define what a subclass must contain. These abstract members declare that a member of a particular type is required; it does not implement the member. Implementation of abstract members takes place within the derived class. A subclass that derives from an abstract class and fails to implement abstract methods will generate syntax errors at compile time.

Declaring a C# abstract class

In addition to using the class modifier, as we have seen in previous examples, abstract classes must also be declared using the abstract modifier:

Abstract classes are declared using the abstract modifier placed before the class modifier:

public abstract class Talk {
}

Abstract class member methods and properties are also declared using the abstract keyword. For example, to declare an abstract method in our Talk class, the following code is required:

public abstract class Talk {
     public abstract void Speak();
}

We now have an abstract class with an abstract method named Speak(). Note that this declaration only states that any class derived from the Talk base class must implement a method called Speak() which returns no value (i.e., it is declared as void) and has no parameters. It does not, however, implement the method.

Deriving from an abstract class

To subclass from an abstract class, we simply write code as follows:

public class SayHello : Talk {
}

We now have a class named SayHello , which is derived from the abstract Talk class. The next step is to implement the abstract Speak() method. The override modifier must be used when implementing abstract members in a derived class. For example:

public override void Speak() {
    Console.WriteLine("Hello!");
}

We now have a subclass derived from the Talk abstract class, which implements the abstract Speak() method.

We can now bring all of this together into a simple program:

class DemoClass
{
    public abstract class Talk
    {
        public abstract void Speak();
    }
  
    public class SayHello : Talk
    {
        public override void Speak()
        {
            System.Console.WriteLine("Hello!");
        }
    }
  
    static void Main()
    {
        SayHello demo = new SayHello();
        demo.Speak();
    }
}

The difference between abstract and virtual members

So far, we have only looked at abstract class members. As discussed above, an abstract member is not implemented in the base class and must be implemented in derived classes for the class to compile.

Another type of member is a virtual member. A member defined as virtual must be implemented in the base class but may optionally be overridden in the derived class if different behavior is required. Such methods are declared using the virtual modifier in the base class.

For example, the following example implements a virtual method in the Talk class:

class DemoClass
{
    public abstract class Talk
    {
        public abstract void Speak();

        public virtual void Goodbye()
		{
			System.Console.WriteLine("Talk class says goodbye!");
		}

    }
  
    public class SayHello : Talk
    {
        public override void Speak()
        {
            System.Console.WriteLine("Hello!");
        }
    }
  
    static void Main()
    {
        SayHello demo = new SayHello();
        demo.Speak();
        demo.Goodbye();
    }
}

If we decide that the default Goodbye() method provided by the Talk class is not suitable for the requirements of the SayHello subclass, we can simply implement our own version of the method using the override modifier:

class DemoClass
{
    public abstract class Talk
    {
        public abstract void Speak();

        public virtual void Goodbye()
		{
			System.Console.WriteLine("Talk class says goodbye!");
		}

    }
  
    public class SayHello : Talk
    {
        public override void Speak()
        {
            System.Console.WriteLine("Hello!");
        }

        public override void Goodbye()
        {
            base.Goodbye();
            System.Console.WriteLine ("SayHello class says goodbye!");
        }
    }
  
    static void Main()
    {
        SayHello demo = new SayHello();
        demo.Speak();
        demo.Goodbye();
    }
}

Now when the code executes, the implementation of the Goodbye() method in the subclass is called.

As with non-abstract classes, a subclass may call the base class implementation of a virtual method. For example, the subclass version of the Goodbye() method could be modified to also call the overridden base class Goodbye() method as follows:

public override void Goodbye()
{
    base.Goodbye();
    System.Console.WriteLine ("SayHello class says goodbye!");
}

Categories