Главная arrow Язык программирования C# arrow C# Полное руководство Герберт Шилдт arrow Создание многоуровневой иерархии классов C# Полное руководство Герберт Шилдт

Создание многоуровневой иерархии классов C# Полное руководство Герберт Шилдт

В представленных до сих пор примерах программ использовались простые иерархии классов, состоявшие только из базового и производного классов. Но в C# можно также строить иерархии, состоящие из любого числа уровней наследования. Как упоминалось выше, многоуровневая иерархия идеально подходит для использования одного производного класса в качестве базового для другого производного класса. Так, если имеются три класса, А, В и С, то класс С может наследовать от класса В, а тот, в свою очередь, от класса А. В таком случае каждый производный класс наследует характерные особенности всех своих базовых классов. В частности, класс С наследует все члены классов В и А.
Для того чтобы показать, насколько полезной может оказаться многоуровневая иерархия классов, рассмотрим следующий пример программы. В ней производный класс Triangle служит в качестве базового для создания другого производного класса — ColorTriangle. При этом класс ColorTriangle наследует все характерные особенности, а по существу, члены классов Triangle и TwoDShape, к которым добавляется поле color, содержащее цвет треугольника.

// Пример построения многоуровневой иерархии классов.

using System;

class TwoDShape {
   double pri_width;
   double pri_height;

   // Конструктор, используемый по умолчанию.
   public TwoDShape() {
      Width = Height = 0.0;
   }

   // Конструктор для класса TwoDShape.
   public TwoDShape(double w, double h) {
      Width = w;
      Height = h;
   }

   // Сконструировать объект равной ширины и высоты.
   public TwoDShape(double х) {
      Width = Height = x;
   }

   // Свойства ширины и высоты объекта.
   public double Width {
      get { return pri_width; }
      
      set { pri_width = value < 0 ? -value : value; }
   }

   public double Height {
      get { return pri_height; }
      set { pri_height = value < 0 ? -value : value; }
   }

   public void ShowDim() {
      Console.WriteLine("Ширина и высота равны " +
                                    Width + " и " + Height);
   }
}

// Класс для треугольников, производный от класса TwoDShape.
class Triangle : TwoDShape {
   string Style; // закрытый член класса

   /* Конструктор, используемый по умолчанию.
       Автоматически вызывает конструктор, доступный по
       умолчанию в классе TwoDShape. */
   public Triangle () {
      Style = "null";
   }

   // Конструктор.
   public Triangle (
                string s, double w, double h) : base (w, h) {
      Style = s;
   }

   // Сконструировать равнобедренный треугольник.
   public Triangle(double x) : base(x) {
      Style = "равнобедренный";
   }

   // Возвратить площадь треугольника.
   public double Area() {
      return Width * Height / 2;
   }

   // Показать тип треугольника.
   public void ShowStyle() {
      Console.WriteLine("Треугольник " + Style);
   }
}

// Расширить класс Triangle.
class ColorTriangle : Triangle {
   string color;

   public ColorTriangle(string c, string s,
                          double w, double h) : base(s, w, h) {
      color = с;
   }

   // Показать цвет треугольника.
   public void ShowColor() {
      Console.WriteLine("Цвет " + color);
   }
}

class Shapes6 {
   static void Main() {
      ColorTriangle t1 =
              new ColorTriangle("синий", "прямоугольный",
                                            8.0, 12.0);
      ColorTriangle t2 =    
              new ColorTriangle"красный", "равнобедренный",
                                            2.0, 2.0);

      Console.WriteLine("Сведения об объекте t1: ");
      t1.ShowStyle();
      t1.ShowDim();
      t1.ShowColor ();
      Console.WriteLine("Площадь равна " + t1.Area());

      Console.WriteLine ();

      Console.WriteLine("Сведения об объекте t2: ");
      t2.ShowStyle();
      t2.ShowDim();
      t2.ShowColor ();
      Console.WriteLine("Площадь равна " + t2.Area());
   }
}

При выполнении этой программы получается следующий результат:
   Сведения об объекте t1:
   Треугольник прямоугольный
   Ширина и высота равны 8 и 12
   Цвет синий
   Площадь равна 48

   Сведения об объекте t2:
   Треугольник равнобедренный
   Ширина и высота равны 2 и 2
   Цвет красный
   Площадь равна 2

Благодаря наследованию в классе ColorTriangle могут использоваться определенные ранее классы Triangle и TwoDShape, к элементам которых добавляется лишь та информация, которая требуется для конкретного применения данного класса. В этом отчасти и состоит ценность наследования, поскольку оно допускает повторное использование кода.
Приведенный выше пример демонстрирует еще одно важное положение: ключевое слово base всегда обозначает ссылку на конструктор ближайшего по иерархии базового класса. Так, ключевое слово base в классе ColorTriangle обозначает вызов конструктора из класса Triangle, а ключевое слово base в классе Triangle — вызов конструктора из класса TwoDShape. Если же в иерархии классов конструктору базового класса требуются параметры, то все производные классы должны предоставлять эти параметры вверх по иерархии, независимо от того, требуются они самому производному классу или нет.