Обзор ООП

‹Объяснено в Overwatch /›

Моя первая встреча

Когда я только стал разработчиком, термин объектно-ориентированное программирование присутствовал почти в каждой статье о вакансиях и подготовке к собеседованию. Что это было и почему это было важно? Я знал, что это за объект, но были ли они каким-то образом связаны? Как это повлияет на мое понимание и реализацию кода?

Документация была продвинутой для новичка, и ее часто было трудно разобрать. Мне было трудно понять объем или разницу между == и ===. Так что я пишу эту статью, чтобы не только повысить свой уровень понимания, но и развлечь других. Я надеюсь, что, используя популярную игру Overwatch для иллюстрации этой парадигмы программирования, вы найдете эту статью интуитивно понятной и познавательной, как и я, когда ее писал.

Итак ... Что это?

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

Внутри объекта мы называем переменные свойствами, а функции методами. Давайте возьмем Гэндзи в качестве примера. Гэндзи - это объект со свойствами, такими как роль, сложность и способности. Такие методы, как shuriken (), deflect () и dragonblade (). Вы можете смоделировать любого героя как объект, каждый со своими свойствами и методами.

От процедурного к объектно-ориентированному

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

Что, если программу расширили? Чтобы внести изменения, мне пришлось бы перебрать кучу отдельных переменных и функций. Функции, которые сильно зависели друг от друга, также известны как сильная связь. Чтобы увидеть разницу между плотным и свободным сцеплением, щелкните здесь! Чтобы понять эти взаимозависимые отношения, мы рассмотрим в качестве примера нагнетатель Orisa.

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

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

ООП на помощь!

Напомним, мы смоделировали Гэндзи как объект, чтобы понять его свойства и методы. Затем мы подчеркнули сходство между нагнетателем Orisa и взаимозависимостью функций в моих программах. Теперь давайте посмотрим на реальный пример кода, чтобы увидеть структурные различия с ООП.

В нашем примере PP ниже у нас есть три переменные (данные) и функция (действие над этими данными), которая принимает три параметра. После рефакторинга в ООП у нас есть объект heroStat с тремя свойствами, методом и функцией без параметров. Чтобы понять, почему это более эффективно, мы обратимся к основным концепциям.

Пример процедурного программирования (PP):

Пример объектно-ориентированного программирования (ООП):

1: инкапсуляция

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

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

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

Преимущество: снижает сложность и увеличивает возможность повторного использования.

2: Абстракция

Чтобы объяснить, что такое абстракция, давайте взглянем на наших персонажей поддержки. Подумайте о таких героях, как Батист, Мерси и Лусио, и это лишь некоторые из них. Батист - это объект типа «Батист», а Лючио - это объект типа «Люцио». И «Baptiste», и «Lucio» являются классами с различными атрибутами, но оба являются подклассами, производными от класса «SupportHeroes» и разделяют свойства и методы, общие для всех героев поддержки.

Несмотря на то, что Мерси и Бриджит имеют разные способности (атрибуты), они имеют одно и то же свойство исцелять своих союзников. Таким образом, «SupportHeroes» - это абстрактный класс. Эти классы используются для определения общего поведения и атрибутов (способностей) определенного типа объекта (Поддержка). Любой физический объект, который вы создаете, всегда будет подклассом «SupportHeroes».

Еще одно преимущество - снижение воздействия изменений. Если мы решим внести изменения в эти частные и внутренние методы, никакие изменения не ускользнут наружу. У нас нет кода, который полагался бы на эти методы вне их содержащего объекта. Мы могли изменить параметры метода или полностью удалить его, и ни одно из этих изменений не повлияло бы на остальной код приложения.

Преимущество: снижает сложность и исключает влияние изменений.

3: Наследование

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

Объект: автономный компонент, содержащий свойства и методы, необходимые для использования данных определенного типа.

Класс: шаблон для создания объекта определенного типа. Как и наш пример класса SupportHeroes, Zenyatta является подклассом класса поддержки.

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

Преимущество: устраняет избыточный код и увеличивает возможность повторного использования.

4: полиморфизм

Полиморфизм можно описать как предоставление различных функциональных возможностей функции, когда различные типы данных переменных передаются в качестве параметров. Чтобы лучше понять эту функцию, мы посмотрим на сотрудников Mercy's Caduceus. Посох Мерси излучает связанный луч на своих товарищей по команде. В зависимости от того, какую кнопку вы нажмете, этот луч либо лечит, либо увеличивает урон этого товарища по команде. Хотя функциональные возможности посоха Кадуцея меняются в зависимости от типа ввода, это тот же посох и тот же луч.

В программировании полиморфизм - это способность вызывать один и тот же метод с разными параметрами и иметь результат изменения метода в зависимости от того, что ему передается. Просто разные классы могут определять один и тот же метод или свойство. Это происходит, когда у нас есть много классов, связанных друг с другом посредством наследования. Мы используем эти унаследованные методы для выполнения разных задач, что позволяет нам выполнять одно действие разными способами.

Преимущество: устраняет избыточный код и увеличивает возможность повторного использования.

Победа!

Мы достигли цели! Используя наших любимых героев из Overwatch, мы подчеркнули преимущества объектно-ориентированного программирования и описали его основные концепции. Однако миссия только началась. Сейчас идеальное время для дальнейшего расширения вашего понимания этой фундаментальной модели языка программирования.