Выбрать главу

Рассмотрим следующий код, который заставляет массив элементов производных от Shape типов визуализировать себя с использованием метода Draw():

Shape[] myShapes = new Shape[3];

myShapes[0] = new Hexagon();

myShapes[1] = new Circle();

myShapes[2] = new Hexagon();

foreach (Shape s in myShapes)

{

  // Использовать полиморфный интерфейс!

  s.Draw();

}

Console.ReadLine();

На этом краткий обзор основных принципов ООП завершен. Оставшийся материал главы посвящен дальнейшим подробностям поддержки инкапсуляции в языке С#, начиная с модификаторов доступа. Детали наследования и полиморфизма обсуждаются в главе 6.

Модификаторы доступа C# (обновление в версии 7.2)

При работе с инкапсуляцией вы должны всегда принимать во внимание то, какие аспекты типа являются видимыми различным частям приложения. В частности, типы (классы, интерфейсы, структуры, перечисления и делегаты), а также их члены (свойства, методы, конструкторы и поля) определяются с использованием специального ключевого слова, управляющего "видимостью" элемента для других частей приложения. Хотя в C# для управления доступом предусмотрены многочисленные ключевые слова, они отличаются в том, к чему могут успешно применяться (к типу или члену). Модификаторы доступа и особенности их использования описаны в табл. 5.1.

В текущей главе рассматриваются только ключевые слова public и private. В последующих главах будет исследована роль модификаторов internal и protected internal (удобных при построении библиотек кода и модульных тестов) и модификатора protected (полезного при создании иерархий классов).

Использование стандартных модификаторов доступа

По умолчанию члены типов являются неявно закрытыми (private), тогда как сами типы — неявно внутренними (internal). Таким образом, следующее определение класса автоматически устанавливается как internal, а стандартный конструктор типа — как private (тем не менее, как и можно было предполагать, закрытые конструкторы классов нужны редко):

// Внутренний класс с закрытым стандартным конструктором.

class Radio

{

  Radio(){}

}

Если вы предпочитаете явное объявление, тогда можете добавить соответствующие ключевые слова без каких-либо негативных последствий (помимо дополнительных усилий по набору):

// Внутренний класс с закрытым стандартным конструктором.

internal class Radio

{

  private Radio(){}

}

Чтобы позволить другим частям программы обращаться к членам объекта, вы должны определить эти члены с ключевым словом public (или возможно с ключевым словом protected, которое объясняется в следующей главе). Вдобавок, если вы хотите открыть доступ к Radio внешним сборкам (что удобно при построении более крупных решений или библиотек кода), то к нему придется добавить модификатор public:

// Открытый класс с открытым стандартным конструктором.

public class Radio

{

  public Radio(){}

}

Использование модификаторов доступа и вложенных типов

Как упоминалось в табл. 5.1, модификаторы доступа private, protected, protected internal и private protected могут применяться к вложенному типу. Вложение типов будет подробно рассматриваться в главе 6, а пока достаточно знать, что вложенный тип — это тип, объявленный прямо внутри области видимости класса или структуры. В качестве примера ниже приведено закрытое перечисление (по имени CarColor), вложенное в открытый класс (по имени SportsCar):

public class SportsCar

{

  // Нормально! Вложенные типы могут быть помечены как private.

  private enum CarColor

  {

    Red, Green, Blue

  }

}