Объектно ориентированное программирование для чайников
10 принципов ООП, о которых стоит знать каждому программисту
- Переводы, 21 мая 2019 в 10:17
- Klara Oswald
Многим опытным разработчикам, вероятно, знакома методология объектно-ориентированного программирования (ООП). Кроме известных её принципов (абстракция, инкапсуляция, полиморфизм, наследование и т. д.) существуют и другие — менее известные, но не менее важные и полезные для реализации. Некоторые из них собраны в специальный блок и известны по акрониму SOLID. Эта статья расскажет об этих и других существующих принципах объектно-ориентированной разработки и о том, какие преимущества они предлагают.
Принцип единственной ответственности (SRP)
Соответствует букве S акронима SOLID. Согласно этому принципу, не должно быть более одной причины для изменения класса, или класс должен всегда обрабатывать одну функциональность.
Основное преимущество состоит в том, что такой подход уменьшает связь между отдельным компонентом программного обеспечения и кодом. Если вы добавляете более одной функциональности в один класс, это вводит связь между двумя функциями, и даже если вы меняете только одну из них, есть шанс сломать другую, связанную с ней. Что в свою очередь требует больше раундов тестирования для избежания каких-либо неожиданностей в продакшене.
Принцип открытости/закрытости (OCP)
Соответствует букве O акронима SOLID. Принцип можно выразить так: «Классы, методы или функции должны быть открыты для расширения (добавления новой функциональности) и закрыты для модификации». Такой подход запрещает кому-либо изменять уже опробованный и протестированный код, а значит, он не ломается. В этом и состоит основное преимущество такого подхода.
Ниже приведён пример кода на Java, который нарушает этот принцип:
А вот пример после рефакторинга. Теперь соблюдается принцип открытости/закрытости: при добавлении новой реализации Shape не нужно менять код GraphicEditor .
Принцип подстановки Барбары Лисков (LSP)
Соответствует букве L акронима SOLID. Согласно этому принципу подтипы должны быть заменяемыми для супертипа. Другими словами, методы или функции, работающие с суперклассом, должны иметь возможность без проблем работать также и с его подклассами.
Ивент переехал в онлайн, есть новые даты ( 14 – 15 июля ) , Москва и онлайн, 10 750–138 000 ₽
LSP тесно связан с принципом единственной ответственности и принципом разделения интерфейса.
Если класс реализует больше функциональности, чем подкласс, то последний может не поддерживать некоторые функции и тем самым нарушает данный принцип.
Ниже приведён пример такого кода на Java:
Функция resize() провоцирует неявную ошибку при работе с экземпляром класса Square , потому что позволяет устанавливать отличные друг от друга значения ширины и высоты. Согласно принципу LSP, функции, использующие ссылки на базовые классы, должны иметь возможность использовать объекты производных классов, не зная об этом. Поэтому для корректной работы функция resize() должна проверять, является ли передаваемый объект экземпляром класса Square, и в этом случае не позволять установить разные значения ширины и высоты. Отсюда идёт нарушение принципа.
Принцип разделения интерфейса (ISP)
Соответствует букве I акронима SOLID. Этот принцип подразумевает, что интерфейс, который не используется, не должен быть реализован.
В основном это происходит, когда один интерфейс содержит несколько функциональностей, и клиенту нужна только одна из них, а другие — нет.
Написание интерфейса — сложная задача. Когда он готов, вы не сможете изменить его, не нарушив всю реализацию.
Ещё одно преимущество этого принципа в Java заключается в том, что интерфейс имеет недостаток. Необходимо сначала реализовать все методы, прежде чем какой-либо класс сможет их использовать. Поэтому наличие единственной функциональности означает меньшее количество методов для реализации.
Принцип инверсии зависимостей (DIP)
Соответствует букве D акронима SOLID. Прелесть этого принципа проектирования в том, что любой класс легко тестируется с помощью фиктивного объекта и проще в обслуживании, потому что код создания объекта централизован, а клиентский код не перегружен им.
Ниже приведён пример кода Java, который нарушает принцип инверсии зависимости:
Пример демонстрирует, что AppManager зависит от EventLogWriter . Если вам нужно использовать другой способ уведомления клиента (например push-уведомления, SMS или электронную почту), необходимо изменить класс AppManager .
Эту проблему можно решить с помощью принципа инверсии зависимостей. Вместо того, чтобы AppManager запрашивал EventLogWriter , последний следует внедрить в AppManager явно. Плюсом реализации общего интерфейса позволить внедрять любую реализацию для других способов уведомления.
Теперь перейдём к принципам, которые не входят в пятёрку SOLID, но не менее важны.
DRY (Don’t Repeat Yourself)
Переводится как «не повторяйся» и буквально означает, что нужно уходить от дублирующего кода и по возможности использовать абстракцию для общих вещей.
Если есть одинаковый блок кода в более чем двух местах, вынесите его в отдельный метод. Если вы используете жёстко запрограммированное значение более одного раза, сделайте его общедоступной константой. Преимущество этого принципа заключается в упрощении поддержки вашего кода.
Но важно не злоупотреблять этим принципом. Например, один и тот же код не подойдёт для проверки OrderId и SSN. Их форматы могут не совпадать, и на выходе функция выдаст некорректный результат. В качестве решения можно предусмотреть в методе проверку форматов для подобных наборов чисел.
Инкапсуляция изменяющегося кода
Сервисы стремительно развиваются. Продакшн подразумевает постоянные изменения кода и его поддержку. Отсюда следует второй принцип ООП — инкапсуляция кода, который с большой вероятностью будет изменён в будущем.
Преимущество этого принципа ООП заключается в том, что инкапсулированный код легко тестировать и поддерживать.
Воспользуйтесь алгоритмом, по которому переменные и методы по умолчанию имеют спецификатор private. Затем шаг за шагом увеличиваете доступ при необходимости (с private на protected, с protected на public).
Одним из вариантов инкапсуляции является Фабричный метод. Он инкапсулирует код создания объекта и обеспечивает гибкость для последующего создания новых объектов без влияния на существующий код.
Композиция вместо наследования
Существует два основных способа повторного использования кода: наследование и композиция. Оба они имеют свои преимущества и недостатки, но, как правило, предпочтение рекомендуется отдавать последнему, если это возможно. Обусловлено это тем, что композиция гибче наследования.
Композиция позволяет изменять поведение класса прямо во время выполнения через установку его свойств. Реализуя интерфейсы, вы, таким образом, используете полиморфизм, который обеспечивает более гибкую реализацию.
«Effective Java» Джошуа Блоха также советует отдавать предпочтение композиции вместо наследования. Если вы всё ещё не уверены, вы также можете посмотреть здесь, чтобы узнать, почему композиция лучше, чем наследование для повторного использования кода и его функциональности.
Программирование для интерфейса
Этот принцип подразумевает, что следует по возможности программировать для интерфейса, а не для его реализации. Это даст вам гибкий код, который может работать с любой новой реализацией интерфейса.
Другими словами, нужно использовать тип интерфейса для переменных, возвращаемых типов или типа аргумента метода. Например, использовать для хранения объекта суперкласс, а не подкласс.
Это также рекомендовано во многих книгах по Java, в том числе в Effective Java и Head First design pattern.
Ниже приведён пример для интерфейса в Java:
Принцип делегирования
Не делайте всё самостоятельно, делегируйте это в соответствующий класс. Классическим примером этого принципа являются методы equals() и hashCode() в Java. Если нужно сравнить два объекта, это действие поручается соответствующему классу вместо клиентского.
Основным преимуществом этого принципа является отсутствие дублирования кода и довольно простое изменение поведения. Этот принцип относится также к делегированию событий (событие делегируется соответствующему обработчику).
Заключение
Эти принципы разработки помогают писать гибкий код, стремящийся к высокой связности и низкому зацеплению. Как только вы это освоите, следующим шагом будет изучение шаблонов проектирования для решения общих проблем разработки приложений и программного обеспечения.
Руководство по ООП на PHP
Мы рассмотрим такие понятия, как объектно-ориентированное программирование, классы PHP , конструкторы PHP , деструкторы PHP , магические методы PHP и т.д. Это руководство предназначено для начинающих и опытных программистов, которые хотят изучить PHP ООП , начиная с базового уровня.
Одним из самых значительных изменений в PHP 5 является наличие полностью объектной модели, которая позволяет повысить производительность. К одним из важных новых функций, добавленных в PHP 5 , относятся окончательные и абстрактные методы, классы, интерфейсы, клонирование и магические методы. Мы рассмотрим в данном руководстве ООП PHP примеры применения каждого из них.
В объектно-ориентированном программировании объект обрабатывается так же, как ссылки или указатели. Это значит, что каждая новая переменная содержит ссылку на объект, а не копию всего объекта.
Самой трудной для понимания концепцией являются основы ООП , так как они отличаются от обычного программирования на PHP. Но как только вы поймете основные принципы, сама модель станет для вас простой и понятной.
Что такое ООП на PHP?
Поскольку термин объектно-ориентированное программирование начинается со слова « объект «, то мы можем сказать, что это особый тип программирования, при котором создаются и используются объекты.
Вот объяснение ООП PHP для чайников. Посмотрите на мир вокруг нас, он полон объектов. Солнце, луна, автомобили, деревья, дома и т.д. и т.п. Все это объекты, они имеют атрибуты и функции. В процессе мышления мы оперируем объектами. Когда мы говорим об автомобиле, вы не думаете о колесах, двигателе, сиденьях, дверях, вы думаете о машине, как о вещи, которой она является. Проще говоря, вы думаете с точки зрения субъекта или объекта. Объектная ориентация — это представление в программировании элементов как объектов.
Автомобиль является объектом. Он имеет атрибуты цвета, размера, веса и функцию перемещения. Любой объект без функционала будет бесполезным. В ООП программист использует объекты; каждый объект имеет некоторые атрибуты и функции. В целом программирование сводится к построению модулей с помощью объектов.
Простое определение объектно-ориентированного программирования:
Объектно-ориентированное программирование — это программирование на основе объектов, содержащих данные ( атрибуты ) и методы ( функционал ), которые обрабатывают эти данные. Объекты — это тип данных, определенных программистом, и взаимодействия между различными объектами также определяется программистом.
Другими словами, ООП позволяет программисту группировать аналогичные задачи в классы, класс может содержать данные и функции для доступа к этим данным, связанные друг с другом.
Основы ООП в PHP помогают разработать более простой в обслуживании и управлении код. Чем более чистым и читаемым является код, тем больше шансов многократно использовать его. В результате к системе могут быть применены шаблоны проектирования. В ООП модули создаются и используются в соответствии с требованиями. С помощью объектно-ориентированного программирования на PHP мы можем создавать приложения для сайтов, которые имеют модульную структуру.
Важные термины руководства по ООП на PHP:
Ниже приводится общее определение некоторых важных терминов, которые часто используются в объектно-ориентированном PHP .
Класс
В ООП PHP класс — это тип данных, определенный программистом. Класс содержит данные и функции для работы с этими данными. Данные и функции имеют идентификатор доступа privat. Это означает, что они не видимы за пределами класса. Класс представляет собой шаблон или образец, с которого можно сделать столько копий или экземпляров, сколько необходимо.
Объект
Объект также известен как экземпляр. Когда устанавливается экземпляр класса, создается объект. Если класс — это образец, то объект — это конечное изделие, созданное с помощью образца. После того, как класс был определен, из него может быть создано множество объектов.
Переменная-член
Переменные, определенные в классе, называются переменными-членами. На самом деле это данные, содержащиеся в этом классе, они могут быть изменены функциями только этого класса. Обычно переменные-члены видимы только для этого класса и скрыты от других классов.
Функция-член
Функции, определенные в классе, называются функциями-членами. Они также не видны для других классов. Они используются для изменения переменных-членов, для доступа к данным объекта.
Конструктор
Конструктор — это особый тип функции-члена. Когда устанавливается класс, создается объект, эта функция вызывается автоматически и присваивает начальные значения переменным класса.
Деструктор
Это особый тип функции, которая вызывается автоматически, когда объект удаляется.
Наследование
В PHP 5 ООП наследование – это процесс, при котором класс ( подкласс ) получает все атрибуты и функции другого класса (суперкласса).
Суперкласс
Также известен как базовый или родительский класс — наследуется одним или несколькими подклассами.
Подкласс
Дочерний или производный класс, подкласс наследуется от суперкласса.
Полиморфизм
Это явление в ООП , при котором одна функция может быть использована для различных целей.
Инкапсуляция
Одна из важнейших концепций объектно-ориентированного программирования. Данные и функции, которые работают с этими данными, связываются между собой и не видны другим функциям.
Абстракция
Абстракция означает, что детали реализации функций или классов не видны.
Перезагрузка
Термин ООП , который означает, что функции, имеющие одинаковые имена, но разное количество аргументов, выполняются по-разному.
Классы и объекты:
Класс и объект широко используются в объектно-ориентированном программировании как термины-синонимы, однако по своей сути они сильно отличаются друг от друга. Класс представляет собой шаблон, образец или форму, а объект является продуктом или деталью, отлитой из этого конкретного шаблона или формы.
Возьмем, к примеру, дом. Класс является основой для дома; он имеет размеры, форму, количество дверей, проходов и т.д. Но это только проект, а не сам дом. Когда построен физический дом на основе информации, содержащейся в плане, то он является объектом.
До этого объект был кучей дерева, кирпича, цемента и т.д., из которых в соответствии с информацией из плана был построен дом или объект:
Класс в PHP ООП — это план или шаблон, по которому устанавливается экземпляр класса, создается объект. После того, как был создан класс, мы можем создать столько объектов, сколько захотим. На рисунке, приведенном выше, из одного класса ( плана ) были созданы пять объектов ( домов ). Объект всегда будет соответствовать инструкциям, приведенным в классе, используемом для его создания.
Преимущества ООП на PHP:
- Улучшение архитектуры и более чистый код
Объектно-ориентированный PHP лучше каталогизирован и легко упаковывается, что позволяет задать оптимальную архитектуру. Обычно каждый класс сохраняется в отдельном файле. Процедурные языки характеризуются сложным кодом, который очень трудно читать или понимать. В ООП за счет реализации объектов, содержащих частные данные с четким определением связей между объектами, код является читаемым и чистым.
Объектно-ориентированное программирование делает код повторно используемым. Объекты, созданные однажды, могут быть использованы снова и снова. Программы могут быть построены путем объединения рабочих модулей вместо того, чтобы писать все с нуля. Это экономит время и повышает производительность.
- Простота в обслуживании и обновлении
Объекты имеют собственные данные и функции, вся их структура компактна и сжата, что позволяет легко вносить в код изменения. С помощью обычного процедурного программирования создается код, в котором очень трудно найти точку для внесения изменений. В ООП PHP мы можем добавить новое свойство, а затем добавлять связанные методы для управления этим свойством.
Инкапсуляция означает, что значения переменных объекта не видны извне, следовательно, реализуется безопасность данных. Но если возникает необходимость, доступ к данным может быть получен с помощью модификаторов доступа. Для создания безопасных программ данные и функции-члены в классе могут быть скрыты от других классов. Когда объект создан, для его использования не нужна информация о его реализации.
Наследующий класс получает все характеристики родительского класса, а затем в него добавляются его собственные характеристики. Подкласс наследует переменные и методы суперкласса. Мы можем расширить использование уже существующих классов, а также убрать ненужный код.
Потому что существуют четко определенные объекты, с данными и privat функциями. Существуют четкие направления связей, нет блуждающие данных или методов. Поэтому в ООП намного меньше ошибок. Следовательно, объектно-ориентированное программирование является оптимальным решением для новых систем.
Этот PHP ООП учебник является свободным и полным источником, с помощью которого вы сможете изучить все необходимые приемы.
Данная публикация представляет собой перевод статьи « PHP OOP Tutorial » , подготовленной дружной командой проекта Интернет-технологии.ру
Объектно-ориентированное программирование для чайников
Если эта статья кажется вам банальной — загляните в продвинутый учебник по ООП.
Классы и объекты
Начнем с самого базового понятия, — класса. Класс, он же тип, чтобы не мучить, и не сбивать с толку формулировками, можно объяснить на примере: класс это Собака, либо Кошка , либо Мышка , — всё это классы. А вот Жучка , Мурчик и Микки-Маус , — это экземпляры классов Собака , Кошка , Мышка . Экземпляры классов еще называют объектами. Итак, — Жучка это экземпляр класса Собака , Мурчик , — экземпляр класса Кошка , а Микки-Маус , — экземпляр класса Мышка , другими словами объект. Класс — единственный и неповторимый. У вас могут быть классы очень похожие, как овчарка и доберман, но это всё равно разные классы, хоть и очень похожие. Класс представляет собой набор характеристик/свойств, которые описывают его состояние и действия/методы, которые он может выполнить. Например, — нас есть класс Овчарка, к числу её свойств можно отнести «возраст» и «кличку». Экземпляр класса может выполнять действия, описанные в классе (лаять, сидеть, лежать), а также содержит значения свойств класса (класс Овчарка имеет свойство «возраст», а объект Барбос имеет значение, — 3 года). Помимо свойств и методов, объект имеет собственное имя, не путать со свойством «кличка», вот как это может выглядеть:
Что означает, что у объекта « МояСобака », есть кличка, и эта кличка — Барбос . А бывает и такая ситуация:
Тут у нас объект « ХозяинСобаки », у которого свойство « имя » имеет значение « Василий », а отчество равно « Иванович ».
Похожим образом работают методы (действия) объектов, например:
Методы могут параметризироваться, например, мы знаем что метод «лаять» заданное количество раз:
Объект всегда должен быть создан. Класс существует как факт, то есть, всегда. Создание объекта выглядит в разных языках программирования по-разному, хотя чаще всего это выглядит так:
МояСобака = new Собака()
Так создается новый экземпляр класса Собака. Иногда он может параметризироваться дополнительной информацией, необходимой для объекта (зависит от реализации класса):
МояСобака = new Собака(«Барбос»)
Разум неподготовленный слегка теряется от этих нескольких терминов, но эта модель, если подумать, очень напоминает окружающий нас мир, который довольно просто раскладывается на классы, объекты, свойства и методы. Этот навык очень помогает создавать программистам простую и понятную архитектуру приложения.
Наследование, инкапсуляция, полиморфизм
Три кита объектного ориентирования это: наследование, инкапсуляция и полиморфизм. Без четкого понимания этих вещей программисту тяжело написать хороший объектно-ориентированный код, использовать всю силу этого подхода, а главное устроится на хорошую работу.
В прошлый раз я рассказывал о классах, объектах, свойствах и методах, если с этими понятиями проблем не возникает, дальше тоже всё будет очень просто. Для наглядности я буду приводить короткие куски кода на PHP (на самом деле язык тут не важен, просто мне кажется это самый распространенный на сегодня синтаксис, хоть и более классическим для примеров ООП является java, мне кажется PHP будет более полезным), поясняющие идею, и давать короткие описания.
Как видите здесь Корова (Cow) унаследовала функционал от Животного (Animal) , изменив реализацию метода draw (конкретизируя как корова на самом деле выглядит), и оставив реализацию метода eat() . Это и есть наследование. Теперь инкапсуляция. Сам по себе этот термин означает «сокрытие». Инкапсуляция, это способ сделать невозможным изменения критичных для работы класса свойств или вызова внутренних методов. Например у нас есть требование: каждое животное должно иметь кличку, и кличка, в течении его жизни не должна меняться. Самое правильное в таком случае это принимать кличку в качестве параметра конструктора (метода выполняемого при создании класса), и хранить его во внутреннем, сокрытом свойстве. Например так:
Вот это и есть инкапсуляция. Нет способа изменить кличку снаружи класса, и вы можете быть уверены, что в любом случае, кличка у экземпляра класса будет именно та, что была задана при создании. Ну а теперь полиморфизм. Это тут тоже начнем с примера. Добавим класс Sheep (овца) .
Теперь, предположим что у нас есть класс какого-то животного (любого), и мы всегда можем узнать как оно выглядит, абсолютно независимо от его типа (другими словами с экземпляром какого класса мы имеем дело).
Данный пример будет случайным образом генерировать экземпляр Коровы и Овцы, и рисовать их.
Нужно сказать что данный пример не совсем «чистый» полиморфизм. Дело в том что полиморфизм подразумевает собой реализацию одного и того же интерфейса в разных классах. Объясню: если бы мы не реализовали метод draw() в одном из классов, у нас периодически возникала бы ошибка обращения к несуществующему методу, а в языках со строгой типизицией, ошибка бы возникала еще на стадии компиляции. Чтобы избежать подобных казусов, нужно использовать итерфейсы (interface):
Как только вы указали, что класс должен реализовывать интерфейс, компилятор или интерпретатор берет на себя обязательство проконтролировать что в классе реализованы методы, описанные в интерфейсе, что позволяет отлавливать ошибки еще до запуска приложения. Вот собственно и всё.
Объектно-ориентированное программирование: на пальцах
Статья не мальчика, но мужа.
Настало время серьёзных тем: сегодня расскажем про объектно-ориентированное программирование, или ООП. Это тема для продвинутого уровня разработки, и мы хотим, чтобы вы его постигли.
Из этого термина можно сделать вывод, что ООП — это такой подход к программированию, где на первом месте стоят объекты. На самом деле там всё немного сложнее, но мы до этого ещё доберёмся. Для начала поговорим про ООП вообще и разберём, с чего оно начинается.
Обычное программирование (процедурное)
Чаще всего под обычным понимают процедурное программирование, в основе которого — процедуры и функции. Функция — это мини-программа, которая получает на вход какие-то данные, что-то делает внутри себя и может отдавать какие-то данные в результате вычислений. Представьте, что это такой конвейер, который упакован в коробочку.
Например, в интернет-магазине может быть функция «Проверить email». Она получает на вход какой-то текст, сопоставляет со своими правилами и выдаёт ответ: это правильный электронный адрес или нет. Если правильный, то true, если нет — то false.
Функции полезны, когда нужно упаковать много команд в одну. Например, проверка электронного адреса может состоять из одной проверки на регулярные выражения, а может содержать множество команд: запросы в словари, проверку по базам спамеров и даже сопоставление с уже известными электронными адресами. В функцию можно упаковать любой комбайн из действий и потом просто вызывать их все одним движением.
Что не так с процедурным программированием
Процедурное программирование идеально работает в простых программах, где все задачи можно решить, грубо говоря, десятком функций. Функции аккуратно вложены друг в друга, взаимодействуют друг с другом, можно передать данные из одной функции в другую.
Например, вы пишете функцию «Зарегистрировать пользователя интернет-магазина». Внутри неё вам нужно проверить его электронный адрес. Вы вызываете функцию «Проверить email» внутри функции «Зарегистрировать пользователя», и в зависимости от ответа функции вы либо регистрируете пользователя, либо выводите ошибку. И у вас эта функция встречается ещё в десяти местах. Функции как бы переплетены.
Тут приходит продакт-менеджер и говорит: «Хочу, чтобы пользователь точно знал, в чём ошибка при вводе электронного адреса». Теперь вам нужно научить функцию выдавать не просто true — false, а ещё и код ошибки: например, если в адресе опечатка, то код 01, если адрес спамерский — код 02 и так далее. Это несложно реализовать.
Вы залезаете внутрь этой функции и меняете её поведение: теперь она вместо true — false выдаёт код ошибки, а если ошибки нет — пишет «ОК».
И тут ваш код ломается: все десять мест, которые ожидали от проверяльщика true или false, теперь получают «ОК» и из-за этого ломаются.
Теперь вам нужно:
- либо переписывать все функции, чтобы научить их понимать новые ответы проверяльщика адресов;
- либо переделать сам проверяльщик адресов, чтобы он остался совместимым со старыми местами, но в нужном вам месте как-то ещё выдавал коды ошибок;
- либо написать новый проверяльщик, который выдаёт коды ошибок, а в старых местах использовать старый проверяльщик.
Задача, конечно, решаемая за час-другой.
Но теперь представьте, что у вас этих функций — сотни. И изменений в них нужно делать десятки в день. И каждое изменение, как правило, заставляет функции вести себя более сложным образом и выдавать более сложный результат. И каждое изменение в одном месте ломает три других места. В итоге у вас будут нарождаться десятки клонированных функций, в которых вы сначала будете разбираться, а потом уже нет.
Это называется спагетти-код, и для борьбы с ним как раз придумали объектно-ориентированное программирование.
Объектно-ориентированное программирование
Основная задача ООП — сделать сложный код проще. Для этого программу разбивают на независимые блоки, которые мы называем объектами.
Объект — это не какая-то космическая сущность. Это всего лишь набор данных и функций — таких же, как в традиционном функциональном программировании. Можно представить, что просто взяли кусок программы и положили его в коробку и закрыли крышку. Вот эта коробка с крышками — это объект.
Программисты договорились, что данные внутри объекта будут называться свойствами, а функции — методами. Но это просто слова, по сути это те же переменные и функции.
Объект можно представить как независимый электроприбор у вас на кухне. Чайник кипятит воду, плита греет, блендер взбивает, мясорубка делает фарш. Внутри каждого устройства куча всего: моторы, контроллеры, кнопки, пружины, предохранители — но вы о них не думаете. Вы нажимаете кнопки на панели каждого прибора, и он делает то, что от него ожидается. И благодаря совместной работе этих приборов у вас получается ужин.
Объекты характеризуются четырьмя словами: инкапсуляция, абстракция, наследование и полиморфизм.
Инкапсуляция — объект независим: каждый объект устроен так, что нужные для него данные живут внутри этого объекта, а не где-то снаружи в программе. Например, если у меня есть объект «Пользователь», то у меня в нём будут все данные о пользователе: и имя, и адрес, и всё остальное. И в нём же будут методы «Проверить адрес» или «Подписать на рассылку».
Абстракция — у объекта есть «интерфейс»: у объекта есть методы и свойства, к которым мы можем обратиться извне этого объекта. Так же, как мы можем нажать кнопку на блендере. У блендера есть много всего внутри, что заставляет его работать, но на главной панели есть только кнопка. Вот эта кнопка и есть абстрактный интерфейс.
В программе мы можем сказать: «Удалить пользователя». На языке ООП это будет «пользователь.удалить()» — то есть мы обращаемся к объекту «пользователь» и вызываем метод «удалить». Кайф в том, что нам не так важно, как именно будет происходить удаление: ООП позволяет нам не думать об этом в момент обращения.
Например, над магазином работают два программиста: один пишет модуль заказа, а второй — модуль доставки. У первого в объекте «заказ» есть метод «отменить». И вот второму нужно из-за доставки отменить заказ. И он спокойно пишет: «заказ.отменить()». Ему неважно, как другой программист будет реализовывать отмену: какие он отправит письма, что запишет в базу данных, какие выведет предупреждения.
Наследование — способность к копированию. ООП позволяет создавать много объектов по образу и подобию другого объекта. Это позволяет не копипастить код по двести раз, а один раз нормально написать и потом много раз использовать.
Например, у вас может быть некий идеальный объект «Пользователь»: в нём вы прописываете всё, что может происходить с пользователем. У вас могут быть свойства: имя, возраст, адрес, номер карты. И могут быть методы «Дать скидку», «Проверить заказ», «Найти заказы», «Позвонить».
На основе этого идеального пользователя вы можете создать реального «Покупателя Ивана». У него при создании будут все свойства и методы, которые вы задали у идеального покупателя, плюс могут быть какие-то свои, если захотите.
Идеальные объекты программисты называют классами.
Полиморфизм — единый язык общения. В ООП важно, чтобы все объекты общались друг с другом на понятном им языке. И если у разных объектов есть метод «Удалить», то он должен делать именно это и писаться везде одинаково. Нельзя, чтобы у одного объекта это было «Удалить», а у другого «Стереть».
При этом внутри объекта методы могут быть реализованы по-разному. Например, удалить товар — это выдать предупреждение, а потом пометить товар в базе данных как удалённый. А удалить пользователя — это отменить его покупки, отписать от рассылки и заархивировать историю его покупок. События разные, но для программиста это неважно. У него просто есть метод «Удалить()», и он ему доверяет.
Такой подход позволяет программировать каждый модуль независимо от остальных. Главное — заранее продумать, как модули будут общаться друг с другом и по каким правилам. При таком подходе вы можете улучшить работу одного модуля, не затрагивая остальные — для всей программы неважно, что внутри каждого блока, если правила работы с ним остались прежними.
Плюсы и минусы ООП
У объектно-ориентированного программирования много плюсов, и именно поэтому этот подход использует большинство современных программистов.
- Визуально код становится проще, и его легче читать. Когда всё разбито на объекты и у них есть понятный набор правил, можно сразу понять, за что отвечает каждый объект и из чего он состоит.
- Меньше одинакового кода. Если в обычном программировании одна функция считает повторяющиеся символы в одномерном массиве, а другая — в двумерном, то у них большая часть кода будет одинаковой. В ООП это решается наследованием.
- Сложные программы пишутся проще. Каждую большую программу можно разложить на несколько блоков, сделать им минимальное наполнение, а потом раз за разом подробно наполнить каждый блок.
- Увеличивается скорость написания. На старте можно быстро создать нужные компоненты внутри программы, чтобы получить минимально работающий прототип.
А теперь про минусы:
- Сложно понять и начать работать. Подход ООП намного сложнее обычного функционального программирования — нужно знать много теории, прежде чем будет написана хоть одна строчка кода.
- Требует больше памяти. Объекты в ООП состоят из данных, интерфейсов, методов и много другого, а это занимает намного больше памяти, чем простая переменная.
- Иногда производительность кода будет ниже. Из-за особенностей подхода часть вещей может быть реализована сложнее, чем могла бы быть. Поэтому бывает такое, что ООП-программа работает медленнее, чем функциональная (хотя с современными мощностями процессоров это мало кого волнует).
Что дальше
Впереди нас ждёт разговор о классах, объектах и всём остальном важном в ООП. Крепитесь, будет интересно!
Урок №112. Введение в ООП
Обновл. 31 Дек 2019 |
В уроке №10 мы определили объект в C++ как часть памяти, которая используется для хранения значений. Объект с именем называется переменной.
В традиционном программировании (чем мы занимались до этого момента), программа — это набор инструкций для компьютера, которые определяют данные (через объекты), а затем работают с этими данными (через операторы и функции). Объекты и функции, которые работают с этими данными, являются отдельными единицами, которые объединяются для получения программистом желаемого результата. Из-за того, что они являются отдельными единицами, традиционное программирование часто не позволяет использовать интуитивное представление реальности. Это является делом программиста — управлять и соединять свойства (переменные) с поведением (функциями) соответствующим образом, что приводит к созданию следующего кода:
Так что же тогда является объектно-ориентированным программированием? Для лучшего понимания воспользуемся аналогией. Оглянитесь вокруг — везде находятся объекты: книги, здания, еда и даже Вы. Объекты имеют два основных компонента:
Свойства (например: вес, цвет, размер, прочность, форма и т.д.).
Поведение, которое они могут проявлять (например: открывать что-либо, делать что-то и т.д.).
Свойства и поведение неотделимы друг от друга.
Объектно-ориентированное программирование (сокр. «ООП») предоставляет возможность создавать объекты, которые объединяют свойства и поведение в самостоятельный союз, который затем можно многоразово использовать. Это приводит к созданию следующего кода:
Так не только читабельнее, но и понятнее, кем является объект ( you — Вы) и какое поведение вызывается ( driveTo — поездка). Вместо того, чтобы сосредоточиться на написании функций, мы концентрируемся на определении объектов, которые имеют чёткий набор поведений. Вот почему эта парадигма называется «объектно-ориентированной».
Это позволяет писать программы модульным способом, что упрощает не только написание и понимание кода, но и обеспечивает более высокую степень возможности повторного использования этого кода. Объекты также обеспечивают более интуитивный способ работы с данными, позволяя программисту определить, как он будет взаимодействовать с объектами, и как эти объекты будут взаимодействовать с другими объектами.
Обратите внимание, ООП не заменяет традиционные методы программирования. ООП — это дополнительный инструмент управления сложностью.
Объектно-ориентированное программирование также предоставляет несколько других полезных концепций: наследование, инкапсуляция, абстракция и полиморфизм. Мы рассмотрим каждую из этих концепций в следующих соответствующих уроках. Будет много нового материала, но как только вы разберётесь с ООП, вам уже не захочется возвращаться к традиционному программированию.
Обратите внимание, термин «объект» перегружен, он имеет несколько значений, что может вызывать некоторую путаницу. В традиционном программировании, «объект» — это часть памяти для хранения значений. В объектно-ориентированном программировании, «объект» — это тот же объект, что и в традиционном программировании, но который соединяет в себе как свойства, так и способы поведения. С этого момента, мы будем использовать термин «объект» в объектно-ориентированном смысле.
Курсы «C#.NET Developer»
Курсы «Java Developer»
Курсы «Frontend Developer»
Курсы «JavaScript Developer»
Курсы «Python Developer»
Курсы «Unity/Game Developer»
Поделиться в социальных сетях:
Глава №7. Итоговый тест
Комментариев: 17
«Объектно-ориентированное программирование (ООП) предоставляет возможность создавать объекты, которые соединяют свойства и поведения в самостоятельный союз, который затем можно многоразово использовать. Это приводит к созданию следующего кода: you.driveTo(work); «
( Это что универсальный код для всех случаев жизни ? )
» Так не только читабельнее, но и понятнее, кем является объект (you — вы) и какое поведение вызывается (driveTo — поездка). Вместо сосредоточения на написании функций, мы концентрируемся на определении объектов, которые имеют четкий набор поведений. Вот почему эта парадигма называется «объектно-ориентированной».
Эта фраза приведена вами в тексте . На каком языке она сформулирована ( для кого ?). И кто сможет понять что вы ей хотите сказать .
Прошу немножко по русски и для людей которые только осваивают само понятие ООП.
Еще раз спасибо за качественный перевод и оформление! У Вас прекрасный перевод, так все грамотно выглядит. Не могу нарадоваться, что нашла и подсела на Ваш сайт. Это лучшее, что я видела. Настолько все постепенно и по порядку, так грамотно составлены уроки, что, кажется, по другому невозможно все это объяснить и понять.
Дойдя до данной главы, сделала паузу для разнообразия на Страуструпа «Принципы и практика использования С++» — вот где каша и все в кучу((( Сначала покажут, через 5 страниц только объяснят. Это кошмар, хорошо, что я уже подготовлена Вашим сайтом. В начале книги совсем нет новой информации для меня (после Вашего сайта )
А здесь иногда происходит так: изучаешь урок, вроде все понятно, но мысль в голове — «к чему это? как это может использоваться?» — а в следующем или через 1-2 урока все встает на места и в новом материале все складывается. В этих уроках действительно все с нуля, подробно и без воды. Как вы откопали такое сокровище? Это просто диво дивное) Надеюсь, что у Вас получится перевести все уроки до конца!
Я иногда тоже удивляюсь, насколько всё последовательно. Текущая тема нужна для освоения последующей: уроки переплетаются не только между другими уроками текущей главы, но и между уроками соседних глав. Получается как в математике: если сегодня не разобрался с косинусами/синусами — завтра не разберешься с теоремами косинусов/синусов (как и в случае с теоремой Пифагора нужно знать, что такое катеты и гипотенуза).
Насчет книг. Материал один и тот же. Те же циклы, ООП, классы, типы данных. Но многое зависит от двух вещей: желание учащегося и способа изложения материала. Т.е. даже самый вкусный контент можно запороть унылой подачей, и также даже, казалось бы, сложные темы можно объяснить простыми словами. Конечно, не всё сразу, но потихоньку начинаешь углубляться и понимать.
Спасибо за ваш отзыв. Надеюсь хватит сил перевести уроки до конца
Этот урок по ООП создают ваши умельцы — которые или не хотят , или не могут донести ученикам то для чего нужен Class . Рассказывая об ООП нужно раскрыть не только содержимое ( привести программный код в примерах ), а объяснить людям механизм для чего нужен Class и как его использовать.
Из аналогии обычного программирования нужно сказать , что Class это то место где собираются подпрограммы — функции относящиеся к одной тематике — объекту, например Class Array — массивы данных ( подпрограммы обработки данных в массивах — вычисление среднего , сумм элементов, сортировки и т.п. ) .
Переменные в private: это фактически глобальные переменные которые объявляются для всех подпрограмм в классе ( они видны из любой подпрограммы данного класса ) — зти переменные в private являются параметрами класса .
Для того чтобы их настроить ( занести данные в эти переменные при конкретном обращении ) используетcя SET функция или функция с любым другим именем , которая заносит в переменные указанные в private конкретные значения – инициализирует параметры для одного конкретного объекта ( экземпляра класса).
Функционал get функций это обращение к каким либо подпрограммам обработчикам , которые производят любые вычисления и любые операции с использование данных в переменных private и возвращают результаты .
Так как данные в private видны из любой подпрограммы в данном классе Class , эти данные не нужно указывать каждый раз в параметрах при обращении к подпрограммам обработчикам , они уже имеются в параметрах – private.
За счет этого уменьшается объем кода программы.
Вот как то так , я бы сказал в видео по началу обучению ООП.
Сомневаюсь, что ваше объяснение будет понятным хотя бы для 30% новичков. То, что вы вместили здесь — детальне расписывается в каждом отдельном уроке этой главы.
Посмотрим будет ли мое объяснеие более понятным чем ваше . Может кто нибудь прокомментирует.
Добрый день, Владимир. Я программирую на С++ уже порядком 10 лет. Не принимайте близко к сердцу, но ваше объяснение слишком сумбурно и готов поспорить, что ни один новичок вообще ничего не поймет из сказанного.
Владимир Сергеевич, все вы правильно написали, но начинающему просто непонятно, конкретика будет в соответствующих уроках. Я сам недавно окончил 4-х месячные курсы С++(очень формальные, если бы не ravesli.com не знаю, что и делал бы). Можно было бы еще и наследование, композицию, агрегирование классов вспомнить, дружественные классы, шаблоны классов. Или вспомнить, что классы — модификация структур, пришедших из С и начать их сравнивать. Но сразу это не поймешь, требуется постепенность. В этих уроках есть постепенный переход от простого к более сложному. Поверьте, что когда вам надо делать лабораторную, а теорию вы получите только в следующем модуле — это не есть хорошо и не способствует усвояемости материала.
работаю программистом 2 года, пытаюсь учить своего младшего брата программированию по этим урокам, увидел ваш комментарий, для эксперимента сначала дал прочитать сам материал, потом ваш комментарий, он ничего не понял из того что вы написали, ваш коментарий это как «С++ за час»
Здравствуйте. Очень признателен за эту вводящую в ооп статью. Но всё же мне непонятно,то есть не могу постичь смысла в этом виде программирования. Чтобы объяснить что я имею в виду, и объяснить где я не понимаю, я приведу примеры. Я заранее искренне надеюсь на вашу помощь.
Итак, для меня понятно,что существует некий код,который понимает компилятор, код, который что делает, выполняет какую-то функцию. Достаточно знать каков код нужен для реализации чего то конкретного и программа работает. Это мне понятно. Не понятно ООП. Не понятно как объект,который мы создаем( к примеру кнопка, при нажатии которой, отправляется сообщение кому то) может что то делать,выполнять? Откуда компьютер знает как ему что то сделать? Мы просто пишем название объекта, пишем на английском что он делает и это всё работает? К примеру, я создаю объект,которой называю «кнопка» на английском, пишу на английском что она нажимается, и потом на этом же английском пишу просто банально что она отправляет сообщение кому то и всё? Так работает ооп? Будет она работать? Спасибо ещё раз за помощь.
ООП и обработка нажатия кнопки соотносятся так же, как квадратное с зелёным: квадратное может быть зелёным, но это совсем не одно и то же.
Обработка нажатия кнопки — это взаимодействие с операционной системой по средствам обработки сообщений от неё (от Windows).
ООП — это философия написания программ. То есть, даже не язык программирования, а один из способов писать на нём.
То есть, мухи отдельно, котлеты отдельно. В прочем, программа, призванная обработать сообщения Windows, может быть написана с и с использованием приёмов ООП.
Я обычно не оставляю комментарии, но данное изложение реально одно из самых лучших.
Так как я только изучаю программирование и плюсы мой первый язык, то уроки Дениса Маркова + данный учебник по C++, наверное, лучшая комбинация в мире))
Спасибо и Вам за комментарий и что читаете
Спасибо Вам огромное за грамотные уроки!
Это лучший русскоязычный материал по плюсам с их нюансами из всего, что я находил.
Значит, будем продолжать
Спасибо большое от меня тоже) Я программирую в основном на си, нашёл много чего не знал на вашем сайте) Жду новых статей)
Спасибо, что читаете Буду работать далее.