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

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

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

Объектно-ориентированное программирование (ООП) — это особый подход к написанию программ. Чтобы понять, что такое ООП и зачем оно нужно, будет полезно вспомнить некоторые факты из истории развития информационных технологий. Первые программы вносились в компьютер с помощью переключателей на передней панели компьютера — в то время компьютеры занимали целые комнаты. Такой способ программирования был крайне неэффективным — на подключение кабелей и установку переключателей могло уйти несколько часов, а иногда и целый рабочий день. А сами расчёты занимали считаные минуты. А если один из программистов (над такими компьютерами работала группа сотрудников) неправильно подключил кабель или установил переключатель, то приходилось всё перепроверять. По сути, весь процесс начинался заново.

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

Следующий этап в программировании — это появление языка Ассемблер. Этот язык программирования позволял писать довольно длинные для того времени программы. Но Ассемблер — это язык программирования низкого уровня, т. е. все операции проводятся на уровне «железа». Рассмотрим простейший пример. Сейчас, чтобы на PHP выполнить элементарное действие, например, сложение чисел, достаточно записать:

$result = 2*5;

На языке же Ассемблер для выполнения этой же операции нужно выполнить как минимум три действия — загрузить в один из регистров первое число (команда MOV), загрузить в другой регистр второе число (опять команда MOV), выполнить сложение регистров командой сложения ADD. Результат будет помещён в третий регистр. Названия регистров можно здесь не указывать, так как они зависят от архитектуры процессора, а это ещё один недостаток Ассемблера. Если вам нужно перенести программу на компьютер с другой архитектурой, то придётся переписывать всё с учётом особенностей целевой архитектуры.

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

$a = s + e;

и вам не нужно задумываться, где именно из регистров (или просто в ОЗУ) хранятся значения, присвоенные переменным s и e. Вы также не знаете, куда будет помещено значение переменной a. Вы просто знаете, что к нему можно обратиться по имени a.

Первый язык высокого уровня — FORTRAN (FORmula TRANslator).

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

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

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

С помощью инкапсуляции вы сможете объединить данные и обрабатывающий их код. Инкапсуляция защищает и код, и данные от вмешательства извне. Базовое понятие в ООП — это класс. Грубо говоря, класс — это своеобразный тип переменной. Экземпляр класса (переменная типа класс) называется объектом. В свою очередь, объект — это совокупность данных (свойств) и функций (методов) для их обработки. Данные и методы обработки называются членами класса.

Таким образом, объект — это результат инкапсуляции, поскольку он включает в себя и данные и код их обработки. Далее вы поймёте, как это работает. А пока представьте, что объект — это сумка, собранная по принципу «всё своё ношу с собой».

Члены класса бывают закрытыми и открытыми. Открытые члены класса доступны для других частей программы, которые не являются частью объекта. Закрытые члены доступны только методам самого объекта.

Теперь поговорим о полиморфизме. Если вы программировали на языке C (на обычном, а не на C++), то наверняка знакомы с функциями abs(), fabs(), labs(). Все они вычисляют абсолютное значение числа, но каждая из функций используется для своего типа данных. Если бы C поддерживал полиморфизм, то можно было бы создать одну функцию abs(), но объявить её трижды — для каждого типа данных, а компилятор уже сам выбрал нужный вариант для функции, в зависимости от переданного ей типа данных. Эта практика называется перезагрузкой функций. Перезагрузка функций существенно облегчает труд программиста. Вам нужно помнить в несколько раз меньше названий функций для написания программы.

Полиморфизм позволяет нам манипулировать с объектами путём создания стандартного интерфейса для схожих действий.

Осталось поговорить о наследовании. С помощью наследования один объект может приобретать свойства другого объекта. Заметьте, наследование — это не копирование объекта. При копировании создаётся точная копия объекта, а при наследовании эта копия дополняется уникальными свойствами (новыми членами). Наследование можно сравнить с рождением ребёнка, когда новый человек наследует «свойства» своих родителей, но в то же время не является точной копией одного из родителей.

Всё вышесказанное было истинно для любого полноценного объектно-ориентированного языка программирования. Исключение здесь составляет JavaScript, где поддержка ООП довольно ограничена. Например, нет ни закрытых (приватных), ни открытых свойств и методов. Все свойства и методы являются открытыми. Создание класса сводится к созданию функции конструктора. Полноценной поддержки ООП в Javascript нет и не будет. Но не стоит забывать, что это не Java, а просто скриптовый язык для браузера.