Рассмотрим следующий код, который заставляет массив элементов производных от 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
}
}