Несмотря на всю свою полезность, защищенный доступ пригоден далеко не для всех ситуаций. Так, в классе TwoDShape из приведенного ранее примера требовалось, чтобы значения его членов Width и Height были доступными открыто, поскольку нужно было управлять значениями, которые им присваивались, что было бы невозможно, если бы они были объявлены как protected. В данном случае более подходящим решением оказалось применение свойств, чтобы управлять доступом, а не предотвращать его. Таким образом, модификатор доступа protected следует применять в том случае, если требуется создать член класса, доступный для всей иерархии классов, но для остального кода он должен быть закрытым. А для управления доступом к значению члена класса лучше воспользоваться свойством.

<p>Конструкторы и наследование</p>

В иерархии классов допускается, чтобы у базовых и производных классов были свои собственные конструкторы. В связи с этим возникает следующий резонный вопрос: какой конструктор отвечает за построение объекта производного класса: конструктор базового класса, конструктор производного класса или же оба? На этот вопрос можно ответить так: конструктор базового класса конструирует базовую часть объекта, а конструктор производного класса — производную часть этого объекта. И в этом есть своя логика, поскольку базовому классу неизвестны и недоступны любые элементы производного класса, а значит, их конструирование должно происходить раздельно. В приведенных выше примерах данный вопрос не возникал, поскольку они опирались на автоматическое создание конструкторов, используемых в 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());

  }

}

Перейти на страницу:

Похожие книги