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

Однако имейте в виду, что злоупотребление операторами статического импортирования может привести в результате к путанице. Во-первых, как быть, если метод WriteLine() определен сразу в нескольких классах? Будет сбит с толку как компилятор, так и другие программисты, читающие ваш код. Во-вторых, если разработчик не особенно хорошо знаком с библиотеками кода .NET Core, то он может не знать о том, что WriteLine() является членом класса Console. До тех пор, пока разработчик не заметит набор операторов статического импортирования в начале файла кода С#, он не может быть полностью уверен в том, где данный метод фактически определен. По указанным причинам применение операторов using static в книге ограничено.

К настоящему моменту вы должны уметь определять простые типы классов, содержащие конструкторы, поля и разнообразные статические (и нестатические) члены. Обладая такими базовыми знаниями о конструкции классов, можно приступать к ознакомлению с тремя основными принципами объектно-ориентированного программирования (ООП).

Основные принципы объектно-ориентированного программирования

Все объектно-ориентированные языки (С#, Java, C++, Visual Basic и т.д.) должны поддерживать три основных принципа ООП.

Инкапсуляция. Каким образом язык скрывает детали внутренней реализации объектов и предохраняет целостность данных?

Наследование. Каким образом язык стимулирует многократное использование кода?

Полиморфизм. Каким образом язык позволяет трактовать связанные объекты в сходной манере?

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

Роль инкапсуляции

Первый основной принцип ООП называется инкапсуляцией. Такая характерная черта описывает способность языка скрывать излишние детали реализации от пользователя объекта. Например, предположим, что вы имеете дело с классом по имени DatabaseReader, в котором определены два главных метода: Open() и Close().

// Пусть этот класс инкапсулирует детали открытия и закрытия базы данных.

DatabaseReader dbReader = new DatabaseReader();

dbReader.Open(@"C:\AutoLot.mdf");

// Сделать что-то с файлом данных и закрыть файл.

dbReader.Close();

Вымышленный класс DatabaseReader инкапсулирует внутренние детали нахождения, загрузки, манипулирования и закрытия файла данных. Программистам нравится инкапсуляция, т.к. этот основной принцип ООП упрощает задачи кодирования. Отсутствует необходимость беспокоиться о многочисленных строках кода, которые работают "за кулисами", чтобы обеспечить функционирование класса DatabaseReader. Все, что понадобится — создать экземпляр и отправить ему подходящие сообщения (например, открыть файл по имени AutoLot.mdf, расположенный на диске С:).

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

Роль наследования

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

Диаграмма на рис. 5.2 читается так: "шестиугольник (Hexagon) является фигурой (Shape), которая является объектом (Object)". При наличии классов, связанных такой формой наследования, между типами устанавливается отношение "является" ("is-a"). Отношение "является" называется наследованием.