C# Abstract Classes

What is an Abstract Class?
So far in this tutorial we have considered concrete classes. A concrete class is a simple class with members such as methods and properties. The class describes the functionality of the objects that it can be used to instantiate.
Often, when working with inheritance hierarchies, the least specialized base class cannot fully represent a real object. For example, classes that represent cubes, spheres and other three-dimensional objects can all be assigned properties and methods that permit the calculation of their volume and surface area. However, if the base class for these types represents generic 3D objects, these calculations are not possible. Furthermore, it may be nonsensical to create an instance of such a class.
An abstract class provides all of the characteristics of a concrete class except that it does not permit objects of the type to be created. An abstract class merely defines members that are used for inheritance, defining the functionality of its child classes. These members may themselves be abstract, effectively declaring a placeholder that must be implemented by subclasses. Members may also be concrete, including real functionality, and may be marked as virtual to support polymorphism via method overriding.
Creating an Abstract Class
To demonstrate the use of abstract classes we will create an example project based around the “ThreeDObject” class. This abstract class will include both abstract and concrete methods and properties.
We will then create two concrete subclasses of ThreeDObject to represent cubes and spheres.
To begin, create a new console application named “AbstractClassesDemo”. Add a class file to the project and name it “ThreeDObject”.
Syntax
To declare that a class is abstract, the “abstract” keyword is used as a prefix to the class definition. To change the ThreeDObject class to abstract, modify the standard declaration as follows:
abstract class ThreeDObject
Now that the class is abstract, it will not be possible to instantiate ThreeDObject objects. This can be shown by adding the following code to the Main method of the program. When you attempt to compile the program, an error occurs.
ThreeDObject cube = new ThreeDObject();
Creating an Abstract Property
An abstract property may only be created within an abstract class. Such a property acts as a placeholder only and contains no functionality of its own. Instead, it ensures that any non-abstract class derived from the abstract base class must implement a matching property. If the subclass is also abstract, the property does not need to be declared again unless it is being made concrete.
As with concrete properties, abstract properties are defined with get and set accessors. If the set accessor is omitted then the property will be read-only. For a write-only property, only the set accessor is included. As the abstract property can contain no code, no code block is created for either accessor.
The following code shows examples of read-write, read-only and write-only abstract properties:

public abstract int ReadWriteProperty { get; set; }
public abstract int ReadOnlyProperty { get; }
public abstract int WriteOnlyProperty { set; }

We will add an abstract property to the ThreeDObject to represent the surface area of a three-dimensional object. This read-only property is a good example of an abstract member as it is impossible to determine the surface area for the general type. However, subclasses that represent a specific type of three-dimensional object will be able to perform this calculation.
To create the surface area property, add the following code to the ThreeDObject class:
public abstract double SurfaceArea { get; }
Creating an Abstract Method
Abstract methods may only be created within abstract classes. Like abstract properties, they are a placeholder for methods that must be implemented in subclasses. To create an abstract method, the “abstract” keyword is used as a prefix to the declaration and no code block is created.
To create an abstract method in ThreeDObject that calculates the object’s volume, add the following code to the class:
public abstract double CalculateVolume();
NB: It would be unusual to use a property for calculating the surface area and a method for the volume.
This selection has been made from demonstration purposes only.
Creating Concrete Members in an Abstract Class
Although it is not possible to instantiate an abstract class, it is possible to create concrete members in the class. These members will be inherited by subclasses in exactly the same manner as when inheriting from concrete classes. The members may also be overridden using polymorphism if marked as virtual.
In the ThreeDObject object we will create a single concrete property and a concrete method. The property will hold the height of the three-dimensional object and the method will calculate the ratio between the object’s volume and surface area. This calculation can be performed in the abstract class using the SurfaceArea property and CalculateVolume method, each of which will be defined in any subclass.
Add the property and method to the ThreeDObject using the following code:

public double Height
{
get
{
return _height;
}
set
{
_height = value;
}
}
public double CalculateVolumeToAreaRatio()
{
return CalculateVolume() / SurfaceArea;
}

Inheriting from an Abstract Class
Deriving a subclass from an abstract class is almost identical to inheriting from any other class. The only difference is that the abstract members of the base class must be implemented.
In the three-dimensional object example we will create two subclasses of ThreeDObject. The first will represent cubes and the second will permit the creation of spheres. Each of the classes will implement the property and the method that have been created as abstract members in the ThreeDObject class.
To begin, add two new class files to the project. Create one class file for the “Cube” class and a second for the “Sphere” class. After you have added the two new classes, modify the code so that they inherit from the ThreeDObject class by appending a colon character (:) and the base class name to each declaration.
The code for the classes should be as follows:

// Cube.cs
class Cube : ThreeDObject
{
}
// Sphere.cs
class Sphere : ThreeDObject
{
}

If you attempt to compile the program, you will receive four compiler errors. These indicate that the abstract property and method must be implemented in each subclass.
Implementing the Abstract Members
To complete the two subclasses, the functionality of the abstract members of the superclass must be defined.
This is achieved by overriding the abstract elements using the override keyword.
To calculate the surface area of a cube, the height is squared to calculate the area of a single face. The result is then multiplied by six to include all six faces. The volume of a cube is simply the height cubed. To add these calculations whilst overriding the abstract members, add the following code to the Cube class:

public override double SurfaceArea
{
get
{
return Math.Pow(Height, 2) * 6;
}
}
public override double CalculateVolume()
{
return Math.Pow(Height, 3);
}

The calculations for a sphere are slightly more complex as they use the value of Pi ( ). This value can be retrieved from the “Math” class. The formula for the surface area of a sphere is 4 r2 where “r” is the radius of the sphere. In our example’s case, the radius is half of the Height property value. The formula for the volume of a sphere is 4/3 r3.
To add these calculations, add the following code to the sphere class:

public override double SurfaceArea
{
get
{
return 4 * Math.PI * Math.Pow(Height / 2, 2);
}
}
public override double CalculateVolume()
{
return (4 / 3) * Math.PI * Math.Pow(Height / 2, 3);
}

Testing the Subclasses
We can now test the two subclasses using the Program class and the Main method. To perform a test of the abstract and concrete members of the base class and the overridden members of the Cube and Sphere classes we will create a simple static method that outputs all of the dimensions provided by ThreeDObject. We will call this twice from the Main method, firstly for a cube and then for a sphere. Here is the code required in the Program class and the expected output:

static void Main(string[] args)
{
Cube cube = new Cube();
cube.Height = 2.5;
OutputDimensions("Cube", cube);
Sphere sphere = new Sphere();
sphere.Height = 2.5;
OutputDimensions("Sphere", sphere);
}
static void OutputDimensions(string name, ThreeDObject object3D)
{
Console.WriteLine();
Console.WriteLine(name);
Console.WriteLine("Heightt{0:f2}m", object3D.Height);
Console.WriteLine("Areat{0:f2}m2", object3D.SurfaceArea);
Console.WriteLine("Volumet{0:f2}m3", object3D.CalculateVolume());
Console.WriteLine("V:At{0:f2}", object3D.CalculateVolumeToAreaRatio());
}

/* OUTPUT
Cube
Height 2.50m
Area 37.50m2
Volume 15.63m3
V:A 0.42
Sphere
Height 2.50m
Area 19.63m2
Volume 6.14m3
V:A 0.31
*/

Tagged . Bookmark the permalink.

Leave a Reply