C#. An example of using an abstract class to build class hierarchies




An example of using an abstract class to build class hierarchies

This topic provides a demo in which a hierarchy of three classes is implemented. At the top of the hierarchy, an abstract class is declared. The class contains abstract properties and methods.

Based on this example, you can learn:

  • correctly develop programs using abstract classes, abstract methods and properties;
  • correctly build class hierarchies that maximize the benefits of polymorphism.

Contents


Search other websites:

1. Task

Develop an abstract class Figure, in which you need to implement the following elements:

  • hidden internal field name (figure name);
  • constructor with 1 parameter, initializing the name field with the specified value;
  • property Name to access the internal name field;
  • the Area2 abstract property, intended to obtain the area of the figure;
  • the Area() abstract method, implemented to obtain the area of a figure;
  • virtual method Print(), which displays the name of the figure.

Develop a Triangle class that inherits (extends) the capabilities of the Figure class. The following elements must be implemented in the class:

  • hidden internal fields a, b, c (sides of the triangle);
  • constructor with 4 parameters;
  • methods SetABC(), GetABC() for accessing the fields of the class. Each method receives 3 parameters – the lengths of the sides of the triangle;
  • the Area2 property, which determines the area of a triangle based on its sides a, b, c;
  • method Area() that returns the area of a triangle along its sides;
  • virtual method Print() to display the internal fields of the class. The method refers to the same method of the base class.

Develop a TriangleColor class that inherits (extends) the capabilities of the Triangle class. In the class, implement the following elements:

  • hidden internal field color;
  • a constructor with 5 parameters that calls the constructor of the base class;
  • The Color property, which is intended to access the internal color field;
  • the Area2 property, which calls the base class property of the same name for calculating the area of a triangle;
  • method Area() that returns the area of a triangle along its sides;
  • virtual method Print() to display the internal fields of the class. The method refers to the same method of the base class.

 

2. Solution

2.1. UML class diagram

The hierarchies of the created classes are conveniently displayed using the UML class diagram, which describes the classes and displays the relationship that exists between them.

Figure 1 shows the UML diagram of the classes that represent the solution of this problem.

C#. Inheritance. UML-class diagram

Figure 1. UML-class diagram. Abstract class Figure and two inherited classes Triangle and TriangleColor

 



2.2. The text of the program in C# (with detailed comments)

Below is the text of the program in C# for the Console Application template.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication8
{
  // Abstract Figure class - contains the abstract Area() method
  // and abstract Area2 property
  abstract class Figure
  {
    // 1. Hidden field of the class
    private string name; // Name of figure

    // 2. Class constructor
    public Figure(string name)
    {
      this.name = name;
    }

    // 3. Property of class field access
    public string Name
    {
      get { return name; }
      set { name = value; }
    }

    // 4. An abstract property that returns the area of a figure
    public abstract double Area2 { get; }

    // 5. Abstract method that returns the area of a figure
    //   The method does not have a method body
    public abstract double Area();

    // 6. A virtual method that displays the value of the fields of a class
    public virtual void Print()
    {
      Console.WriteLine("name = {0}", name);
    }
  }

  // A class that implements a triangle.
  // There are no abstract methods in the class,
  // therefore, the keyword abstract is not preceded by a class declaration.
  class Triangle : Figure
  {
    // 1. Internal class fields
    double a, b, c;

    // 2. Class constructor
    public Triangle(string name, double a, double b, double c)
                : base(name)
    {
      // Checking the correctness of the values of a, b, c
      if (((a + b) > c) && ((b + c) > a) && ((a + c) > b))
      {
        this.a = a; this.b = b; this.c = c;
      }
      else
      {
        Console.WriteLine("Incorrect values a, b, c.");
        Console.WriteLine("By default: a=1, b=1, c=1.");
        this.a = this.b = this.c = 1;
      }
    }

    // 3. Implementation of access methods to hidden fields a, b, c
    // 3.1. Set the values of a, b, c fields
    public void SetABC(double a, double b, double c)
    {
      if (((a + b) > c) && ((b + c) > a) && ((a + c) > b))
      {
        this.a = a; this.b = b; this.c = c;
      }
      else
      {
        this.a = this.b = this.c = 1;
      }
    }

    // 3.2. Reading field values - pay attention to out modifier
    public void GetABC(out double a, out double b, out double c)
    {
      a = this.a; b = this.b; c = this.c;
    }

    // 4. Overriding the Area2 abstract property of the Figure class,
    //   keyword override required
    public override double Area2
    {
      get
      {
        // 1. Make calculations
        double p, s;
        p = (a + b + c) / 2;
        s = Math.Sqrt(p * (p - a) * (p - b) * (p - c));

        // 2. Display the result
        Console.WriteLine("Property Triangle.Area2: s = {0:f3}", s);

        // 3. Returning the result
        return s;
      }
    } 

    // 5. An implementation of the Area() method,
    //   which is declared as abstract in the Figure class
    public override double Area()
    {
      // 1. Make calculations
      double p, s;
      p = (a + b + c) / 2;
      s = Math.Sqrt(p * (p - a) * (p - b) * (p - c));

      // 2. Display the result
      Console.WriteLine("Method Triangle.Area(): s = {0:f3}", s);

      // 3. Return the result
      return s;   
    }

    // 6. Virtual method Print()
    public override void Print()
    {
      base.Print();
      Console.WriteLine("a = {0:f2}", a);
      Console.WriteLine("b = {0:f2}", b);
      Console.WriteLine("c = {0:f2}", c);
    }
  }

  // A class that defines a triangle with color
  class TriangleColor : Triangle
  {
    // 1. Hidden field color
    private int color;

    // 2. Constructor with 5 parameters
    public TriangleColor(string name, double a, double b, double c, int color) :
                base(name, a, b, c)
    {
      // Checking the correctness of the color value
      if ((color >= 0) && (color <= 255))
        this.color = color;
      else
        this.color = 0;
    }

    // 3. The property of access to the color field
    public int Color
    {
      get { return color; }

      set
      {
        // Checking the correctness of the color value
        if ((color >= 0) && (color <= 255))
          color = value;
        else
          color = 0;
      }
    }

    // 4. Property Area2 - calls the base class property of the same name
    public override double Area2
    {
      get 
      { 
        // 1. Pre display the control message
        Console.WriteLine("Property TriangleColor.Area2:");

        // 2. Call a base class property
        return base.Area2; 
      }
    }

    // 5. Abstract method Area()
    public override double Area()
    {
      // 1. Display the control message
      Console.WriteLine("Method TriangleColor.Area():");

      // 2. Call a base class property
      return base.Area();
    }

    // 6. Virtual method Print()
    public override void Print()
    {           
      base.Print();
      Console.WriteLine("color = {0}", color);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Demonstration of polymorphism using an abstract class.
      // 1. Declare the reference to base class
      Figure refFg;

      // 2. Declare an instance of class Figure
      // 2.1. Unable to instantiate abstract class
      // Figure objFg = new Figure("Figure"); - error!

      // 2.2. Declare instances of classes Triangle, TriangleColor
      Triangle Tr = new Triangle("Triangle", 2, 3, 2);
      TriangleColor TrCol = new TriangleColor("TriangleColor", 1, 3, 3, 0);

      // 3. Demonstration of polymorphism using
      //   the Print() method as an example
      refFg = Tr;
      refFg.Print();

      refFg = TrCol;
      refFg.Print();

      // 4. Demonstration of polymorphism
      //   using the example of the Area() method
      refFg = Tr;
      refFg.Area(); // invoke method Triangle.Area()

      refFg = TrCol;
      refFg.Area(); // invoke method TriangleColor.Area()

      // 5. Demonstration of polymorphism
      //   using the example of the Area2 property
      refFg = Tr;
      double area = refFg.Area2; // property Triangle.Area2
      Console.WriteLine("area = {0:f3}", area);

      refFg = TrCol;
      area = refFg.Area2; // property TriangleColor.Area2
      Console.WriteLine("area = {0:f3}", area);

      Console.ReadKey();
    }
  }
}

 

2.3. The result of the program

 

name = Triangle
a = 2.00
b = 3.00
c = 2.00
name = TriangleColor
a = 1.00
b = 3.00
c = 3.00
color = 0
Method Triangle.Area(): s = 1.984
Method TriangleColor.Area():
Method Triangle.Area(): s = 1.479
Property Triangle.Area2: s = 1.984
area = 1.984
Property TriangleColor.Area2:
Property Triangle.Area2: s = 1.479
area = 1.479

 


Related topics