Объектно-ориентированное программирование, самая запутанная тема среди новичков! Но это имеет очень большое значение, когда речь идет о более чистом способе программирования. Вы ведь ожидаете чего-то простого и легкого способа начать работу с основами управления операциями, не так ли? Фантастика! Вы попали в нужное место, я постараюсь охватить эту тему множеством реальных примеров и аналогий, чтобы вы всегда могли сравнить концепцию с этими аналогиями, чтобы полностью понять концепцию! И уверяю вас, что эти концепции сразу навсегда впишутся в ваш мозг! Итак, садитесь на борт этого автомобиля OOPS, и приступим!

Есть четыре основных концепции oop, которые вы, возможно, уже преодолели, а именно:

1. ЭНКАПСУЛЯЦИЯ
2. АБСТРАКЦИЯ
3. НАСЛЕДОВАНИЕ
4. ПОЛИМОРФИЗМ

Но давайте не будем начинать со всего этого жаргона, давайте начнем строить эти концепции одну за другой, зная, зачем они нам нужны из первых рук! 🧐
Итак, мы все пользуемся коммутатором, верно? (Вы можете задаться вопросом, как это связано с уп?). Давайте посмотрим . . .

Допустим, вы жили в мире, где коммутаторы выглядели вот так: все соединительные провода были доступны, но не было кнопок для взаимодействия! Насколько легко включать и выключать вентилятор?

Вы можете посмотреть на распределительный щит и отделить провода, относящиеся к вентилятору, от проводов, относящихся к лампочке, и так далее, а затем вы можете каким-то образом соединить провода вентилятора и, наконец, включить вентилятор! 🥱

Немного сложно, правда? Вы можете немного научиться понимать, как работают эти соединения, и включать и выключать вентилятор, когда это необходимо! Итак, можем ли мы сказать, что эта реализация неверна? Нет ! Это, тем не менее, работает и выполняет свою работу, но кому-то сложно использовать его напрямую (и очень небезопасно! Что, если вы случайно подключите два провода вентилятора и один провод лампы 😐).

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

Что вы можете наблюдать в приведенном выше коде? У вас есть прибор, и у него есть 3 провода для подключения. Для каждого устройства вы создаете 3 переменные для представления проводов, и используются те 2 функции, которые соответственно подключают и переключают переключатель.
Подумайте: что, если бы у вас было другое устройство, и вы хотите его использовать?
Итак, в приведенный выше код вы добавите еще 3 переменные для представления проводов, а затем вызовете эти 2 функции для переключения включать и выключать прибор.

Что, если у вас есть еще 100 приборов, и все они подключены к этому распределительному щиту? 🥺🥺. Вы должны создать по 3 переменные для каждого устройства и вызвать эти 2 метода! Подумайте, сколько повторений кода вам придется делать !!! Это может вызвать серьезные проблемы с ремонтопригодностью кода в крупномасштабных проектах!

Согласно принципу СУХОЙ (Не повторяйся), вы всегда должны стремиться избегать дублирования в своем коде! Давайте решим эту проблему. Но с чего начать?
Посмотрим, что повторяется в нашем коде.

wire1_red = somevalue
wire1_brown = somevalue
wire1_white = somevalue

Если внимательно посмотреть, весь этот повторяющийся код связан с каждым устройством. Так почему бы не объединить все это в одно целое и не предоставить простой интерфейс для взаимодействия?

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

В этом вся идея инкапсуляции!
Инкапсуляция: заключите (что-нибудь) в капсулу или как бы в нее.

Согласно инкапсуляции-

  1. Нам нужно упаковать все связанные поля (все 3 проводные переменные) и функциональность (метод переключения переключателя) в один объект. [Для связи с нашим примером - все провода были упакованы и соединены внутри коммутатора и предоставили пользователю чистый интерфейс.].

Здесь вы можете видеть, что все поля и методы, относящиеся к устройству, помещены в класс.

NOTE: This section is for beginners who don’t know what class is. Please skip this part if you already know about it.
Class is similar to a blueprint, which contains related fields and functions to implement a certain behavior.
Let’s say to implement car behavior, you can create a class Car and it can have certain properties like 
1. speed,
2. mileage,
and some functions like
1. def moveCar()
2. def applyBreak() and so on.
But this is not a car yet! This is just a blueprint. To bring a car alive we have to create an object out of the blueprint.
In most of the languages you can create an object like this:
myNewCar = Car()
So the variable myNewCar is an actual car now! You can access its properties or call its methods now. For ex:
$print(myNewCar.mileage)
$myNewCar.applyBreak()

2. Предоставляйте пользователю только те поля и методы, которые необходимы. [Провода не были нужны пользователю для использования прибора (и были небезопасными!). Поэтому попробуйте скрыть эти провода от пользователя].

В приведенном выше коде вы можете заметить, что поля класса теперь закрыты с помощью двойного подчеркивания. Это означает, что поле предназначено «только для внутреннего использования» (является частным для класса) и не может быть доступно извне класса.

Здесь можно сделать три важных вывода:

1. «Поля становятся закрытыми», что обеспечивает лучшую безопасность, поскольку поля данных класса не будут изменены внешними методами!

2. «Некоторые методы класса сделаны закрытыми». Здесь метод connectWires сделан частным, так как пользователю не нужно знать или изменять способ подключения проводов (что, если вы подключили неправильные провода и привели к короткому замыканию 😂, поэтому никогда не предоставляйте доступ пользователю или клиенту, который он не должен доступ).

3. Вся эта идея инкапсуляции связанных полей и ограничения доступа к некоторым полям, делая их частными для класса, передает «состояние класса» в руки методов, которые он предоставляет (общедоступные методы), поэтому объект всегда остается в контроль и становится сам себе хозяином!

Теперь вы можете подумать, как мог бы выглядеть код, если бы у вас было 100 устройств, подключенных к коммутатору?

Выглядит так просто, правда? Да, это так 😀

Следовательно, инкапсуляция дает следующие преимущества:

  1. Повторное использование 🤨 (мы видели, как дублирование кода было преодолено с помощью класса).
  2. Ремонтопригодность😮 (поскольку теперь код стал намного чище, предположим, что даже если мы захотим изменить количество проводов, используемых переключателем, мы можем легко сделать это изменение в классе, и это не повлияет ни на один из код пользователя!)
  3. Скрытие данных 🙆‍♂️ (Мы видели, как сделать определенные поля закрытыми, чтобы повысить безопасность приложения. Объект всегда остается согласованным, пока его состояние не перейдет в руки методов, которые он предоставляет!)

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

Теперь, когда вы освоили инкапсуляцию 😉, вы обрели уверенность и попытались создать приложение для потоковой передачи видео, такое как NETFLIX🎥 !. Изначально вы сделали приложение, доступное для iOS, Android и в Интернете. На всех трех платформах вы можете обеспечить потоковое видео с качеством не более 480p на данный момент без возможности загрузки, и вы планируете улучшить качество в будущем. Прямо сейчас вы создали класс VideoPlayer на основе вашего обучения, который инкапсулирует все связанные поля. Как показано ниже, это текущая реализация класса VideoPlayer 🎬.

Поскольку у вас гораздо большая кодовая база с сотнями файлов, вы разделили код для каждой платформы (Android, IOS и Интернет) на отдельные файлы, чтобы сохранить чистую структуру и избежать путаницы. Как показано ниже, код для Интернета, Android и IOS сейчас тот же. Все создают объект класса VideoPlayer и используют методы play, pause ...

Так что пока здесь все в порядке! 😊. Теперь вы становитесь знаменитыми, поэтому вы думаете о введении новых функций -
1. Поддержка потоковой передачи 1080p.
2. Поддержка параметров загрузки видео.
3. Не позволяйте пользователям смотреть видео в Интернете, после показа короткого вступления к видео сообщите им, чтобы они загрузили приложение, чтобы продолжить просмотр.

Но из-за технических проблем вы могли добавить только первые две функции в Android, поэтому пользователям iOS придется подождать :(

Я ненадолго остановлюсь. Можете ли вы тем временем пролистать приведенный выше код и подумать 💭, какие изменения вам нужно сделать, чтобы поддержать эти новые функции на Android? 🤔

Один из возможных подходов - добавить отдельные методы, специфичные для Android и Интернета, в класс VideoPlayer. Все методы были изменены для поддержки каждой платформы отдельно.

Увидев приведенный выше код, вы можете заметить, что старые методы были переименованы для поддержки каждой платформы отдельно в классе VideoPlayer, и, следовательно, каждая IOS, веб и Android должны изменить свой код, чтобы адаптироваться к этому новому изменению.

Теперь новый код для Android выглядит так:

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

Как показано ниже, эта новая функция оказывает такое же влияние на IOS и веб-код. Представьте себе, каков будет реальный сценарий в больших приложениях!

Так какое же решение?

Как насчет класса, в котором есть такие методы, как playVideo (), downloadVideo (), pauseVideo (). . . и если вы вызываете их из iOS, Android или Интернета, они работают так, как будто знают, что делать с конкретной платформой. Для Android playVideo будет воспроизводить 1080p, а для других - 480p и так далее.

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

В приведенном выше классе есть некоторые из этих методов, например playVideo, downloadVideo и pause_play_Video. Они не реализованы и оставлены пустыми для тех, кто хочет их реализовать. Это похоже на то, что если вы хотите получить функции VideoPlayer, вы должны реализовать эти методы в обязательном порядке. Например: правительство говорит, что если вы хотите продать машину, то она должна иметь звуковой сигнал, индикаторы, подушки безопасности и т. Д., Иначе вам не разрешат продать машину. Следовательно, вы либо создаете автомобиль, в котором реализованы все эти функции, либо вообще не создаете автомобиль!

Таким образом, у нас может быть 3 отдельных класса для IOS, Интернета и Android, и каждый из них будет реализовывать эти вышеупомянутые методы в соответствии со своими требованиями !. Ниже представлена ​​реализация.

Здесь вы можете заметить, что все 3 класса были написаны отдельно, и каждый из них реализовал эти 3 абстрактных метода в соответствии со своими требованиями!

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

Можете ли вы подумать, как будет выглядеть код обработчика для конкретной платформы?

Да! вы можете заметить, что все обработчики (только 2 показаны выше) теперь используют одни и те же имена методов (playVideo вместо playVideoIOS, playVideoWEB). Обработчик iOS создаст экземпляр класса VideoPlayerIOS, веб-обработчики и обработчики Android будут создавать экземпляры своего собственного соответствующего класса. И все эти классы реализуют абстрактные методы, поэтому все имеют одинаковые имена.

Вы видите это большое преимущество? Если нет, подумайте, какие изменения необходимы, чтобы IOS поддерживала потоковую передачу 1080p и возможность загрузки видео?

ДА. Вы правы 😃, изменив только реализацию методов класса videoPlayerIOS, мы сможем добиться этого добавления новой функции, и больше ничего менять нигде не нужно! Просто прокрутите вверх и наведите указатель мыши на коды, и вы поймете эту большую разницу!

Вы только что видели, как лучше спроектированное программное обеспечение упрощает обслуживание всего приложения и снижает сложность и накладные расходы на управление кодом?

Это точное представление о том, что такое АБСТРАКЦИЯ! Абстракция помогает скрыть сложность. Инкапсуляция способствует сокрытию элементов данных, а абстракция способствует скрытию методов.

ОСНОВНЫЕ ПРЕИМУЩЕСТВА АБСТРАКЦИИ: 🦝

  1. Он отделяет подпись метода от его реализации.
  2. Для пользователей это предохраняет их от воздействия чего-либо, кроме сигнатур методов, которые им необходимо знать, что снижает сложность.
  3. Помогает избежать повторяющегося кода
  4. Предоставляет программистам возможность изменять реализацию абстрактного поведения.

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

Мы встретимся снова в следующей серии, где я расскажу о наследовании и полиморфизме!

Любопытно, как я это узнал?

Это часть июльского выпуска #IBELIEVEINDOING CHALLENGE, подготовленного CRIO.DO.
Я обнаружил это недавно как сообщение в Instagram, и мне повезло, что я нашел это! Метод обучения на практике действительно полезен, поскольку знания сохраняются в течение более длительного времени по сравнению с традиционным обучением.

Рекомендую посмотреть на их потрясающие работы на https://crio.do/ натура.

Надеюсь, вы нашли эту статью полезной 😃! Если да, то хлопните 👏. (Вы тоже можете много хлопать 😉).

Подпись! До скорой встречи.