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

Конструкторы и наследование C# Полное руководство Герберт Шилдт

В иерархии классов допускается, чтобы у базовых и производных классов были свои собственные конструкторы. В связи с этим возникает следующий резонный вопрос: какой конструктор отвечает за построение объекта производного класса: конструктор базового класса, конструктор производного класса или же оба вместе? На этот вопрос можно ответить так: конструктор базового класса конструирует базовую часть объекта, а конструктор производного класса — производную часть этого объекта. И в этом есть своя логика, поскольку базовому классу неизвестны и недоступны любые элементы производного класса, а значит, их конструирование должно происходить раздельно. В приведенных выше примерах данный вопрос не возникал, поскольку они опирались на автоматическое создание конструкторов, используемых в C# по умолчанию. Но на практике конструкторы определяются в большинстве классов. Ниже будет показано, каким образом разрешается подобная ситуация.
Если конструктор определен только в производном классе, то все происходит очень просто: конструируется объект производного класса, а базовая часть объекта автоматически конструируется его конструктором, используемым по умолчанию. В качестве примера ниже приведен переработанный вариант класса Triangle, в котором определяется конструктор, а член Style делается закрытым, так как теперь он устанавливается конструктором.

// Добавить конструктор в класс Triangle.

using System;

// Класс для двумерных объектов.
class TwoDShape {
   double pri_width;
   double pri_height;

   // Свойства ширины и длины объекта.
   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;

   // Конструктор.
   public Triangle(string s, double w, double h) {
      Width = w; // инициализировать член базового класса
      Height = h; // инициализировать член базового класса
      Style = s; // инициализировать член производного класса
   }

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

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

class Shapes3 {
   static void Main() {
      Triangle t1 = new Triangle(
                                 "равнобедренный", 4.0, 4.0);
      Triangle t2 = new Triangle(
                                 "прямоугольный", 8.0, 12.0);

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

      Console.WriteLine();

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


В данном примере конструктор класса Triangle инициализирует наследуемые члены класса TwoDShape вместе с его собственным полем Style.
Когда конструкторы определяются как в базовом, так и в производном классе, процесс построения объекта несколько усложняется, поскольку должны выполняться конструкторы обоих классов. В данном случае приходится обращаться к еще одному ключевому слову языка С#: base, которое находит двоякое применение: во-первых, для вызова конструктора базового класса; и во-вторых, для доступа к члену базового класса, скрывающегося за членом производного класса. Ниже будет рассмотрено первое применение ключевого слова base.