На этом шаге мы рассмотрим, на чем базируется объектно-ориентированная парадигма.
Как мы уже знаем, язык программирования C# - полностью объектно ориентированный. Это означает, что в нем реализована парадигма ООП. В чем же особенность ООП? Важно понимать, что речь идет о способе организации программы. На сегодня существует два основных способа организации программного кода. Это объектно-ориентированное и процедурное (структурное) программирование. Попробуем разобраться, чем отличаются эти концепции программирования.
При процедурном программировании программа реализуется как набор подпрограмм (процедуры и функции), используемых для обработки данных. То есть данные, используемые в программе, и программный код, применяемый для обработки этих данных, существуют отдельно друг от друга. В процессе выполнения программы выбираются нужные данные и обрабатываются с помощью специальных процедур и функций. Если провести аналогию, то можно такой способ программирования и организации программы сравнить с кухней. На этой кухне стоят холодильники и специальные боксы с продуктами. Это данные. Еще на кухне есть повара, которые из продуктов готовят блюда. Повара - это аналог процедур и функций. Есть шеф-повар (которого можно отождествить с программой или, как в нашем случае, с главным методом). Шеф-повар определяет блюда, которые должны готовить его подчиненные, и какие продукты (из какого холодильника или бокса) должны использоваться. Что не так в этой схеме? Да, в общем-то, все нормально. Если шеф-повар профессиональный, а команда поваров подобрана грамотно, то обязанности будут распределены правильно и кухня будет работать нормально. Так все происходит, если кухня нс очень большая. Но если у вас огромный цех, в котором много поваров и холодильников с продуктами, то могут возникнуть проблемы организационного характера: кто-то не в своем холодильнике продукты взял, кто-то заказ неправильно понял. При этом повара-исполнители могут быть высочайшими профессионалами и продукты могут быть отменного качества. Но этого мало. Важно еще и правильно организовать процесс. А если кухня большая, то сделать это непросто. Какой выход из ситуации? Реорганизация. Разбиваем весь большой кухонный цех на блоки, в каждом блоке есть свой сушеф (главный повар в блоке), у него есть подчиненные. У каждого блока есть своя специализация. Один блок готовит первые блюда, другой готовит салаты, третий готовит десерты, и так далее. В каждом блоке свои холодильники и боксы с продуктами, предназначенными именно для этого блока. Шеф-повар общается с сушефами в блоках. Им он раздает задания, а они уже контролируют работу своих блоков. То есть сушефы организуют и контролируют работу блока, а шеф-повар руководит работой кухни на уровне взаимодействия разных блоков. А что там происходит внутри каждого отдельного блока - не его забота. Собственно, это и есть объектно ориентированный подход. При таком подходе программа представляет собой "сцену", на которой взаимодействуют "объекты". "Объектами" в нашем "кухонном" примере являются блоки. Каждый "объект" содержит в себе данные (холодильники с продуктами) и методы, обрабатывающие данные (повара, которые используют продукты), и все это локализовано в объекте. Главное удобство описанного подхода в том, что мы сразу распределяем и группируем данные и программный код, предназначенный для обработки этих данных. Это потенциально уменьшает вероятность ошибочного использования данных и облегчает создание программы.
Можно привести и другую аналогию для иллюстрации разницы между процедурным и объектно ориентированным программированием. Допустим, нам нужно построить дом. Мы его можем строить из кирпичей. Если дом не очень большой, то такая технология вполне удачная. Из кирпичей можно выложить практически все что угодно, реализовать любой дизайнерский проект. Но все это хорошо, пока мы не решили строить многоэтажный дом. Если так, то технологию, скорее всего, придется поменять. Намного удобнее строить такой дом из блоков. Каждый блок заранее изготавливается на специальном заводе. Блок содержит окна, двери и другие полезные элементы. И весь дом складывается из блоков. Это будет быстрее и надежнее по сравнению со случаем, когда мы строим из кирпичей.
Строительство дома из кирпичей - аналог программы, которая создается в рамках концепции процедурного программирования. Строительство дома из блоков аналог программы, созданной в рамках концепции ООП. Мы в этом случае "строим" программу не из маленьких "кирпичиков", а из больших "блоков", которые имеют еще и некоторую функциональность.
Таким образом, ООП - это способ организации программы через взаимодействие отдельных объектов, содержащих данные и методы для работы с этими данными. Обычно в ООП выделяют три базовых принципа:
Любой объектно ориентированный язык содержит средства для реализации этих принципов. Способы реализации могут отличаться, но принципы неизменны.
Инкапсуляция означает, что данные объединяются в одно целое с программным кодом, предназначенным для их обработки. Фактически организация программы через взаимодействие объектов является реализацией принципа инкапсуляции. На программном уровне инкапсуляция реализуется путем использования классов и объектов (объекты создаются на основе классов).
Полиморфизм подразумевает использование единого интерфейса для решения однотипных задач. Проявлением полиморфизма является тот факт, что нередко в программе один и тот же метод можно вызывать с разными аргументами. Это удобно. Если вернуться к аналогии с кухней, то ситуация примерно такая: шеф-повар дает задание своим поварам, указывая название блюда. При этом ему нет необходимости уточнять, как именно блюдо готовится. Все это знают повара, выполняющие заказ. Они определяют, какие продукты нужно использовать. Если в какой-то момент поменяется рецепт приготовления блюда (например, один продукт будет заменен другим), шеф-повар будет называть все то же блюдо. Изменение рецепта автоматически учтут повара, которые готовят блюдо.
Наследование позволяет создавать объекты не на пустом месте, а с использованием ранее разработанных утилит. В языке C# наследование позволяет создавать классы на основе уже существующих классов. Эти классы используются для создания объектов. Вообще название этого механизма очень точно отображает его сущность. Он занимает важное место в концепции языка С#, и мы обязательно вернемся к обсуждению этого вопроса.
Далее мы перейдем к более приземленным вопросам. В частности, познакомимся с классами и объектами. Концепция классов и объектов является фундаментальной для понимания принципов реализации ООП в языке С#.
На следующем шаге мы рассмотрим классы и объекты.