По ооп: Шпаргалка по принципам ООП

Содержание

Шпаргалка по принципам ООП

Чтобы стать программистом, нужно знать принципы ООП как Отче наш. Держите структурированную шпаргалку по объектно-ориентированному программированию.

Главное

  • Инкапсулируйте все, что может изменяться;
  • Уделяйте больше внимания интерфейсам, а не их реализациям;
  • Каждый класс в вашем приложении должен иметь только одно назначение;
  • Классы — это их поведение и функциональность.

Базовые принципы ООП

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

Используйте следующее вместе с наследованием

  • Делегация — перепоручение задачи от внешнего объекта внутреннему;
  • Композиция — включение объектом-контейнером объекта-содержимого и управление его поведением; последний не может существовать вне первого;
  • Агрегация — включение объектом-контейнером ссылки на объект-содержимое; при уничтожении первого последний продолжает существование.

Не повторяйся (Don’t repeat yourself — DRY)

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

Принцип единственной обязанности

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

Принцип открытости/закрытости

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

Принцип подстановки Барбары Лисков

Методы, использующие некий тип, должны иметь возможность использовать его подтипы, не зная об этом.

Принцип разделения интерфейсов

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

Принцип инверсии зависимостей

Система должна конструироваться на основе абстракций «сверху вниз»: не абстракции должны формироваться на основе деталей, а детали должны формироваться на основе абстракций.

Перевод статьи «Object-Orientated Design Principles»

 

ООП в картинках / Хабр

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



Прежде всего стоит ответить, зачем? Объектно-ориентированная идеология разрабатывалась как попытка связать поведение сущности с её данными и спроецировать объекты реального мира и бизнес-процессов в программный код. Задумывалось, что такой код проще читать и понимать человеком, т. к. людям свойственно воспринимать окружающий мир как множество взаимодействующих между собой объектов, поддающихся определенной классификации. Удалось ли идеологам достичь цели, однозначно ответить сложно, но де-факто мы имеем массу проектов, в которых с программиста будут требовать ООП.

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

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

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

Классы и объекты

Сразу лирическое отступление: объектно-ориентированный подход возможен и без классов, но мы будем рассматривать, извиняюсь за каламбур, классическую схему, где классы — наше всё.

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

Таким образом, класс — это описание того, какими свойствами и поведением будет обладать объект. А объект — это экземпляр с собственным состоянием этих свойств.

Мы говорим «свойства и поведение», но звучит это как-то абстрактно и непонятно. Привычнее для программиста будет звучать так: «переменные и функции». На самом деле «свойства» — это такие же обычные переменные, просто они являются атрибутами какого-то объекта (их называют полями объекта). Аналогично «поведение» — это функции объекта (их называют методами), которые тоже являются атрибутами объекта. Разница между методом объекта и обычной функцией лишь в том, что метод имеет доступ к собственному состоянию через поля.

Итого, имеем методы и свойства, которые являются атрибутами. Как работать с атрибутами? В большинстве ЯП оператор обращения к атрибуту — это точка (кроме PHP и Perl). Выглядит это примерно вот так (псевдокод):

// объявление класса с помощью ключевого слова class
class Transformer(){
    // объявление поля x
    int x

    // объявление метода конструктора (сюда нам чуть ниже передадут 0)
    function constructor(int x){
        // инициализация поля x 
        // (переданный конструктору 0 превращается в свойство объекта)
        this.x = x
    }
	
    // объявление метода run
    function run(){
        // обращение к собственному атрибуту через this
        this.x += 1
    }
}

// а теперь клиентский код:

// создаем новый экземпляр трансформера с начальной позицией 0
optimus = new Transformer(0)

optimus.run() // приказываем Оптимусу бежать
print optimus.x // выведет 1
optimus.run() // приказывает Оптимусу еще раз бежать
print optimus.x // выведет 2

В картинках я буду использовать такие обозначения:

Я не стал использовать UML-диаграммы, посчитав их недостаточно наглядными, хоть и более гибкими.


Анимация №1

Что мы видим из кода?

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

optimus.x, то изнутри, если Оптимус захочет сам обратиться к своему полю x, в его методе обращение будет звучать так: this.x, то есть «я (Оптимус) обращаюсь к своему атрибуту x«. В большинстве языков эта переменная называется this, но встречаются и исключения (например, self)

2. constructor — это специальный метод, который автоматически вызывается при создании объекта. Конструктор может принимать любые аргументы, как и любой другой метод. В каждом языке конструктор обозначается своим именем. Где-то это специально зарезервированные имена типа __construct или __init__, а где-то имя конструктора должно совпадать с именем класса. Назначение конструкторов — произвести первоначальную инициализацию объекта, заполнить нужные поля.

3. new — это ключевое слово, которое необходимо использовать для создания нового экземпляра какого-либо класса. В этот момент создается объект и вызывается конструктор. В нашем примере, конструктору передается 0 в качестве стартовой позиции трансформера (это и есть вышеупомянутая инициализация). Ключевое слово new в некоторых языках отсутствует, и конструктор вызывается автоматически при попытке вызвать класс как функцию, например так: Transformer().

4. Методы constructor и run работают с внутренним состоянием, а во всем остальном не отличаются от обычных функций. Даже синтаксис объявления совпадает.

5. Классы могут обладать методами, которым не нужно состояние и, как следствие, создание объекта. В этом случае метод делают статическим.

SRP

(Single Responsibility Principle / Принцип единственной ответственности / Первый принцип

SOLID

). С ним вы, наверняка, уже знакомы из других парадигм: «одна функция должна выполнять только одно законченное действие». Этот принцип справедлив и для классов: «Один класс должен отвечать за какую-то одну задачу». К сожалению с классами сложнее определить грань, которую нужно пересечь, чтобы принцип нарушался.

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

Ассоциация

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

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

class Gun(){ // объявляем класс Пушка
    int ammo_count // объявляем количество боеприпасов

    function constructor(){ // конструктор
        this.reload() // вызываем собственный метод "перезарядить"
    }

    function fire(){ // объявляем метод пушки "стрелять"
        this.ammo_count -= 1 // расходуем боеприпас из собственного магазина
    }

    function reload(){ // объявляем метод "перезарядить"
        this.ammo_count = 10 // забиваем собственный магазин боеприпасами
    }
}

class Transformer(){ // объявляем класс Трансформер
    Gun gun_left // объявляем поле "левая пушка" типа Пушка
    Gun gun_right // объявляем поле "правая пушка" тоже типа Пушка
    
    /*
    теперь конструктор Трансформера принимает
    в качестве аргументов две уже конкретные созданные пушки,
    которые передаются извне
    */
    function constructor(Gun gun_left, Gun gun_right){
        this.gun_left = gun_left // устанавливаем левую пушку на борт
        this.gun_right = gun_right // устанавливаем правую пушку на борт
    }
    
    // объявляем метод Трансформер "стрелять", который сначала стреляет...
    function fire(){
        // левой пушкой, вызывая ее метод "стрелять"
        this.gun_left.fire()
        // а затем правой пушкой, вызывая такой же метод "стрелять"
        this.gun_right.fire()
    }
}

gun1 = new Gun() // создаем первую пушку
gun2 = new Gun() // создаем вторую пушку
optimus = new Transformer(gun1, gun2) // создаем трансформера, передавая ему обе пушки


Анимация №2

this.gun_left.fire() и this.gun_right.fire() — это обращения к дочерним объектам, которые происходят так же через точки. По первой точке мы обращаемся к атрибуту себя (this.gun_right), получая объект пушки, а по второй точке обращаемся к методу объекта пушки (this.gun_right.fire()).

Итог: робота сделали, табельное оружие выдали, теперь разберемся, что тут происходит. В данном коде один объект стал составной частью другого объекта. Это и есть ассоциация. Она в свою очередь бывает двух видов:

1. Композиция — случай, когда на фабрике трансформеров, собирая Оптимуса, обе пушки ему намертво приколачивают к рукам гвоздями, и после смерти Оптимуса, пушки умирают вместе с ним. Другими словами, жизненный цикл дочернего объекта совпадает с жизненным циклом родительского.

2. Агрегация — случай, когда пушка выдается как пистолет в руку, и после смерти Оптимуса этот пистолет может подобрать его боевой товарищ Олег, а затем взять в свою руку, либо сдать в ломбард. То бишь жизненный цикл дочернего объекта не зависит от жизненного цикла родительского, и может использоваться другими объектами.

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

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

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

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

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

class Transformer(){ // базовый класс
    function run(){
        // код, отвечающий за бег
    }
    function fire(){
        // код, отвечающий за стрельбу
    }
}

class Autobot(Transformer){ // дочерний класс, наследование от Transformer
    function transform(){
        // код, отвечающий за трансформацию в автомобиль
    }
}

class Decepticon(Transformer){ // дочерний класс, наследование от Transformer
    function transform(){
        // код, отвечающий за трансформацию в самолет
    }
}

optimus = new Autobot()
megatron = new Decepticon()



Анимация №3

Сей пример наглядно иллюстрирует, как наследование становится одним из способов дедуплицировать код (DRY-принцип) с помощью родительского класса, и одновременно предоставляет возможности для мутации в классах-потомках.

Перегрузка

Если же в классе-потомке переопределить уже существующий метод в классе-родителе, то сработает перегрузка. Это позволяет не дополнять поведение родительского класса, а модифицировать. В момент вызова метода или обращения к полю объекта, поиск атрибута происходит от потомка к самому корню — родителю. То есть, если у автобота вызвать метод fire(), сначала поиск метода производится в классе-потомке — Autobot, а поскольку его там нет, поиск поднимается на ступень выше — в класс Transformer, где и будет обнаружен и вызван. Следует отметить, что модификация нарушает

LSP

из набора принципов

SOLID

, но мы рассматриваем только техническую возможность.

Неуместное применение

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

золотого молотка

. Но это совершенно не означает, что наследование в принципе всегда вредит. Мой нарколог говорил, что первый шаг — это признать, что у тебя зависимость от наследования.

Как при описании отношений двух сущностей определить, когда уместно наследование, а когда — композиция? Можно воспользоваться популярной шпаргалкой: спросите себя, сущность А является сущностью Б? Если да, то скорее всего, тут подойдет наследование. Если же сущность А является частью сущности Б, то наш выбор — композиция.

Применительно к нашей ситуации это будет звучать так:

  1. Автобот является Трансформером? Да, значит выбираем наследование.
  2. Пушка является частью Трансформера? Да, значит — композиция.

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

Наследование статично

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

метапрограммирование

).

Множественное наследование

Мы рассмотрели ситуацию, когда два класса унаследованы от общего потомка. Но в некоторых языках можно сделать и наоборот — унаследовать один класс от двух и более родителей, объединив их свойства и поведение. Возможность наследоваться от нескольких классов вместо одного — это множественное наследование.

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

Абстрактные классы

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

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

Полиморфизм

Полиморфизм — свойство системы, позволяющее иметь множество реализаций одного интерфейса. Ничего непонятно. Обратимся к трансформерам.

Положим, у нас есть три трансформера: Оптимус, Мегатрон и Олег. Трансформеры боевые, стало быть обладают методом attack(). Игрок, нажимая у себя на джойстике кнопку «воевать», сообщает игре, чтобы та вызвала метод attack() у трансформера, за которого играет игрок. Но поскольку трансформеры разные, а игра интересная, каждый из них будет атаковать каким-то своим способом. Скажем, Оптимус — объект класса Автобот, а Автоботы снабжаются пушками с плутониевыми боеголовками (да не прогневаются фанаты трансформеров). Мегатрон — Десептикон, и стреляет из плазменной пушки. Олег — басист, и он обзывается. А в чем польза?

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

Инкапсуляция

Инкапсуляция — это контроль доступа к полям и методам объекта. Под контролем доступа подразумевается не только можно/неможно, но и различные валидации, подгрузки, вычисления и прочее динамическое поведение.

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

  • publiс — к атрибуту может получить доступ любой желающий
  • private — к атрибуту могут обращаться только методы данного класса
  • protected — то же, что и private, только доступ получают и наследники класса в том числе
class Transformer(){
    public function constructor(){ }

    protected function setup(){ }

    private function dance(){ }
}

Как правильно выбрать модификатор доступа? В простейшем случае так: если метод должен быть доступен внешнему коду, выбираем public. В противном случае — private. Если есть наследование, то может потребоваться protected в случае, когда метод не должен вызываться снаружи, но должен вызываться потомками.

Аксессоры (геттеры и сеттеры)

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

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

Интерфейсы

Задача интерфейса — снизить уровень зависимости сущностей друг от друга, добавив больше абстракции.

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

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

Классы с интерфейсами состоят в отношении «многие ко многим»: один класс может имплементировать множество интерфейсов, и каждый интерфейс, в свою очередь, может имплементироваться многими классами.

У интерфейса двустороннее применение:

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

Например, если какой-то объект помимо основного поведения, может быть сериализован, то пускай он имплементирует интерфейс «Сериализуемый». А если объект можно склонировать, то пусть он имплементирует еще один интерфейс — «Клонируемый». И если у нас есть какой-то транспортный модуль, который передает объекты по сети, он будет принимать любые объекты, имплементирующие интерфейс «Сериализуемый».

Представим, что каркас трансформера оборудован тремя слотами: слот для оружия, для генератора энергии и для какого-нибудь сканера. Эти слоты обладают определенными интерфейсами: в каждый слот можно установить только подходящее оборудование. В слот для оружия можно установить ракетную установку или лазерную пушку, в слот для генератора энергии — ядерный реактор или РИТЭГ (радиоизотопный термоэлектрический генератор), а в слот для сканера — радар или лидар. Суть в том, что каждый слот имеет универсальный интерфейс подключения, а уже конкретные устройства должны соответствовать этому интерфейсу. К примеру, на материнских платах используется несколько типов слотов: слот для процессора позволяет подключать различные процессоры, подходящие под данный сокет, а слот SATA — любой SSD или HDD накопитель или даже CD/DVD.

Обращаю внимание, что получившаяся система слотов у трансформеров — это пример использования композиции. Если же оборудование в слотах будет сменным в ходе жизни трансформера, то тогда это уже агрегация. Для наглядности, мы будем называть интерфейсы, как принято в некоторых языках, добавляя заглавную «И» перед именем: IWeapon, IEnergyGenerator, IScanner.

// описания интерфейсов:

interface IWeapon{
    function fire() {} // декларация метода без имплементации. Ниже аналогично
}

interface IEnergyGenerator{
    // тут уже два метода, которые должны будут реализовать классы:
    function generate_energy() {} // первый
    function load_fuel() {}       // второй
}

interface IScanner{
    function scan() {}
}


// классы, реализующие интерфейсы:

class RocketLauncher() : IWeapon
{
    function fire(){
        // имплементация запуска ракеты
    }
}

class LaserGun() : IWeapon
{
    function fire(){
        // имплементация выстрела лазером
    }
}

class NuclearReactor() : IEnergyGenerator
{
    function generate_energy(){
        // имплементация генерации энергии ядерным реактором
    }
	
    function load_fuel(){
        // имплементация загрузки урановых стержней
    }
}

class RITEG() : IEnergyGenerator
{
    function generate_energy(){
        // имплементация генерации энергии РИТЭГ
    }
	
    function load_fuel(){
        // имплементация загрузки РИТЭГ-пеллет
    }
}

class Radar() : IScanner
{
    function scan(){
        // имплементация использования радиолокации
    }	
}

class Lidar() : IScanner
{
    function scan(){
        // имплементация использования оптической локации
    }
}

// класс - потребитель:

class Transformer() {
    // привет, композиция:
    IWeapon slot_weapon   // Интерфейсы указаны в качестве типов данных.
    IEnergyGenerator slot_energy_generator // Они могут принимать любые объекты,
    IScanner slot_scanner // которые имплементируют указанный интерфейс
	
    /*
    в параметрах методов интерфейс тоже указан как тип данных,
    метод может принимать объект любого класса,
    имплементирующий данный интерфейс:
    */
    function install_weapon(IWeapon weapon){ 
        this.slot_weapon = weapon
    }
	
    function install_energy_generator(IEnergyGenerator energy_generator){
        this.slot_energy_generator = energy_generator
    }
	
    function install_scanner(IScanner scanner){
        this.slot_scanner = scanner
    }
}

// фабрика трансформеров

class TransformerFactory(){
    function build_some_transformer() {
       	transformer = new Transformer()
       	laser_gun = new LaserGun()
       	nuclear_reactor = new NuclearReactor()
       	radar = new Radar()
       	
       	transformer.install_weapon(laser_gun)
       	transformer.install_energy_generator(nuclear_reactor)
       	transformer.install_scanner(radar)
        	
        return transformer
    }
}

// использование

transformer_factory = new TransformerFactory()
oleg = transformer_factory.build_some_transformer()



Анимация №4

К сожалению, в картинку не влезла фабрика, но она все равно необязательна, трансформера можно собрать и во дворе.

Обозначенный на картинке слой абстракции в виде интерфейсов между слоем имплементации и слоем-потребителем дает возможность абстрагировать одних от других. Вы можете это наблюдать, посмотрев на каждый слой в отдельности: в слое имплементации (слева) нет ни слова про класс Transformer, а в слое-потребителе (справа) нет ни слова про конкретные имплементации (там нет слов Radar, RocketLauncher, NuclearReactor и т. д.)

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

Утиная типизация

Явление, которое мы наблюдаем в получившейся архитектуре, называется

утиной типизацией

:

если что-то крякает как утка, плавает как утка, и выглядит как утка, то, скорее всего — это утка

.

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

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

ISP

(Interface Segregation Principle / Принцип разделения интерфейса / Четвертый принцип SOLID) призывает не создавать жирные универсальные интерфейсы. Вместо этого интерфейсы нужно разделять на более мелкие и специализированные, это поможет гибче их комбинировать в имплементирующих классах, не заставляя имплементировать лишние методы.

Абстракция

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

Уровень абстракции

Тут нельзя не процитировать одну известную шутку:


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

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

Неверный выбор уровня абстракции ведет к одной из двух проблем:

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

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

Давайте рассмотрим определение уровня абстракции из возможных вариантов на примере гипотетической игры «трансформеры-онлайн». Уровни абстракции в данном случае будут выступать как слои, каждый последующий рассматриваемый слой будет ложиться поверх предыдущего, забирая из него часть функционала в себя.

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

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

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

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

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

Паттерны проектирования


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

Паттерны проектирования, как и абстракция, свойственны не только ООП разработке, но и другим парадигмам. Вообще, тема паттернов выходит за рамки данной статьи, но здесь хотелось бы предостеречь молодого разработчика, который только намерен познакомиться с паттернами. Это ловушка! Сейчас объясню, почему.

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

Еще одна ценность от паттернов — формализации терминологии. Гораздо проще коллеге сказать, что в этом месте используется «цепочка обязанностей», чем полчаса рисовать поведение и отношения объектов на бумажке.

Заключение

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

Хочется закончить свою песнь важными словами. Любые описанные механизмы, принципы и паттерны, как и ООП в целом не стоит применять там, где это бессмысленно или может навредить. Это ведет к появлению статей со странными заголовками типа «Наследование — причина преждевременного старения» или «Синглтон может приводить к онкологическим заболеваниям».

Я серьезно. Если рассмотреть случай с синглтоном, то его повсеместное применение без знания дела, стало причиной серьезных архитектурных проблем во многих проектах. И любители забивать гвозди микроскопом любезно его нарекли антипаттерном. Будьте благоразумны.

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

ТОП книги по объектно-ориентированному программированию (ООП)

Просмотров 6.4k. Обновлено

Что почитать по объектно-ориентированному программированию? Отобрали лучшие книги по ООП для начинающих. Актуальная литература на русском языке с лучшими оценками.

Паттерны объектно-ориентированного проектирования. Ральф Джонсон, Эрих Гамма, Ричард Хелм, Джон Влиссидес

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

Показана роль паттернов в создании архитектуры сложных систем и принципы их использования. Для удобства читателя они объединены в каталог.

Для кого предназначено:

  • программисты, которые учатся объектно-ориентированному программированию;
  • профессиональные разработчики.

Computer Science. Роберт Седжвик, Кевин Уэйн

Очень подробный учебник по языку Java. Его создатели — преподаватели одного из старейших в США университетов — Принстонтского.

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

Теория для наглядности показана на примерах: прикладная математика, физика и биология, визуализация данных, обработка графики, числовые методы, финансовое моделирование, синтез звука.

Предметно-ориентированные языки программирования. Мартин Фаулер

Книга предназначена для профессионалов, но и начинающие программисты могут найти в ней полезное для себя. Состоит из двух частей:

  • обзор главных принципов и основ предметно-ориентированных языков программирования;
  • решение конкретных задач, чтобы было понятно, какую методику, где и как применять.

Как правило, примеры в книге даются на Java и C#, но в некоторых автор использует Ruby. Все главы организованы как отдельные самостоятельные части, а большинство справочных разделов как описания шаблонов программирования.

Объектно-ориентированное программирование в С++. Роберт Лафоре

Книга дает знакомство практически с нуля с технологией объектно-ориентированного программирования в С++. Включает основные принципы языка, готовые приложения, решения конкретных примеров, понятные и подробные иллюстрации. Очень полезно для студентов, потому в книге есть 100 упражнений, которые помогут закрепить знания.

Ruby. Объектно-ориентированное проектирование. Сэнди Метц

Книга-бестселлер по программированию на языке Ruby. Вы сможете научиться писать на Ruby качественный код в духе ООП, определять состав класса Ruby, разграничивать функциональность объектов, научиться утиной типизации, созданию гибких интерфейсов между несколькими объектами, применять полиморфизм, наследование и композицию, оттачивать legacy-код Ruby, делать экономные тесты и многое другое.

Объектно-ориентированное программирование на PHP. Максим Кузнецов, Игорь Симдянов

Книга для профессиональных разработчиков, знакомых с базовыми возможностями PHP, языком HTML и работой с СУБД MySQL. Посвящена воможностям ООП в PHP, изложена доступным для понимания языком. Описаны специальные методы классов, наследование и полиморфизм, интерфейсы, инкапсуляция, статические, константные и final члены класса, особенности длительного хранения объектов, их клонирование, как нужно делать обработку исключений. Много хороших примеров. Есть аудиоматериалы, которые можно скачать с сайта издательства.

Java. Объектно-ориентированное программирование. Алексей Васильев

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

Состоит из двух частей:

  • основы языка Java в объеме, достаточном для написания простых программ;
  • более продвинутые профессиональные темы.

Теория иллюстрирована примерами решений и соответствует программе обучения в вузах. Можно советовать студентам.

Делитесь не попавшими в эту подборку книгами по ООП в комментариях!

Руководство по ООП в PHP

Мы рассмотрим такие понятия, как объектно-ориентированное программирование, классы PHP, конструкторы PHP, деструкторы PHP, магические методы PHP и т.д. Это руководство предназначено для начинающих и опытных программистов, которые хотят изучить ООП в PHP, начиная с базового уровня.

Одним из самых значительных изменений в PHP 5 является наличие полностью объектной модели, которая позволяет повысить производительность. К одним из важных новых функций, добавленных в PHP 5, относятся окончательные и абстрактные методы, классы, интерфейсы, клонирование и магические методы. Мы рассмотрим в данном руководстве ООП PHP примеры применения каждого из них.

В объектно-ориентированном программировании объект обрабатывается так же, как ссылки или указатели. Это значит, что каждая новая переменная содержит ссылку на объект, а не копию всего объекта.

Самой трудной для понимания концепцией являются основы ООП, так как они отличаются от обычного программирования на PHP. Но как только вы поймете основные принципы, сама модель станет для вас простой и понятной.

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

Вот объяснение ООП в PHP для чайников. Посмотрите на мир вокруг нас, он полон объектов. Солнце, луна, автомобили, деревья, дома и т.д. и т.п. Все это объекты, они имеют атрибуты и функции. В процессе мышления мы оперируем объектами. Когда мы говорим об автомобиле, вы не думаете о колесах, двигателе, сиденьях, дверях, вы думаете о машине, как о вещи, которой она является. Проще говоря, вы думаете с точки зрения субъекта или объекта. Объектная ориентация — это представление в программировании элементов как объектов.

Автомобиль является объектом. Он имеет атрибуты цвета, размера, веса и функцию перемещения. Любой объект без функционала будет бесполезным. В ООП программист использует объекты; каждый объект имеет некоторые атрибуты и функции. В целом программирование сводится к построению модулей с помощью объектов.

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

Другими словами, ООП позволяет программисту группировать аналогичные задачи в классы, класс может содержать данные и функции для доступа к этим данным, связанные друг с другом.

Основы ООП в PHP помогают разработать более простой в обслуживании и управлении код. Чем более чистым и читаемым является код, тем больше шансов многократно использовать его. В результате к системе могут быть применены шаблоны проектирования. В ООП модули создаются и используются в соответствии с требованиями. С помощью объектно-ориентированного программирования на PHP мы можем создавать приложения для сайтов, которые имеют модульную структуру.

Ниже приводится общее определение некоторых важных терминов, которые часто используются в объектно-ориентированном PHP.

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

Объект также известен как экземпляр. Когда устанавливается экземпляр класса, создается объект. Если класс — это образец, то объект — это конечное изделие, созданное с помощью образца. После того, как класс был определен, из него может быть создано множество объектов.

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

Функции, определенные в классе, называются функциями-членами. Они также не видны для других классов. Они используются для изменения переменных-членов, для доступа к данным объекта.

Конструктор — это особый тип функции-члена. Когда устанавливается класс, создается объект, эта функция вызывается автоматически и присваивает начальные значения переменным класса.

Это особый тип функции, которая вызывается автоматически, когда объект удаляется.

В PHP 5 ООП наследование – это процесс, при котором класс (подкласс) получает все атрибуты и функции другого класса (суперкласса).

Также известен как базовый или родительский класс — наследуется одним или несколькими подклассами.

Дочерний или производный класс, подкласс наследуется от суперкласса.

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

Одна из важнейших концепций объектно-ориентированного программирования. Данные и функции, которые работают с этими данными, связываются между собой и не видны другим функциям.

Абстракция означает, что детали реализации функций или классов не видны.

Термин ООП, который означает, что функции, имеющие одинаковые имена, но разное количество аргументов, выполняются по-разному.

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

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

До этого объект был кучей дерева, кирпича, цемента и т.д., из которых в соответствии с информацией из плана был построен дом или объект:

Класс в PHP ООП — это план или шаблон, по которому устанавливается экземпляр класса, создается объект. После того, как был создан класс, мы можем создать столько объектов, сколько захотим. На рисунке, приведенном выше, из одного класса (плана) были созданы пять объектов (домов). Объект всегда будет соответствовать инструкциям, приведенным в классе, используемом для его создания.

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

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

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

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

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

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

Это руководством по ООП в PHP является свободным и полным источником, с помощью которого вы сможете изучить все необходимые приемы.

Данная публикация является переводом статьи «PHP OOP Tutorial» , подготовленная редакцией проекта.

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

Разработка веб-приложений с помощью объектно-ориентированного подхода на языке PHP поначалу может сбить с толку тех разработчиков, которые привыкли использовать процедурный подход, но на самом деле ничего сложного в ООП нет. В данном курсе мы рассмотрим теоретические аспекты ООП, а также научимся применять полученные знания на практике.

Курс состоит из 17 уроков, в которых мы шаг за шагом изучим основы ООП, которых должно быть достаточно для написания приложений в объектном стиле.

Изучив этот курс, Вы будете понимать, что такое объектно-ориентированное программирование, узнаете, что такое классы и объекты, а также поймете разницу между ними. Узнаете о свойствах, методах и константах класса.

После прохождения курсы Вы сможете использовать наследование классов для создания удобной и гибкой логики Вашего веб-приложения, создавать разветвленные иерархии классов. Будете уметь переопределять методы и тем самым расширять их функционал, создавать абстрактные классы. Из курса вы узнаете смысл использования интерфейсов и научитесь использовать их там, где это действительно может требоваться, а не использовать интерфейсы ради интерфейсов. Особое внимание в курсе отведено теме автозагрузки классов, что позволит исключить длинные списки подключаемых файлов. Здесь вы узнаете, как о функциях автозагрузки, так и научитесь использовать для этой цели пакетный менеджер Composer.

Все это и многое другое вы узнаете из уроков предлагаемого курса по ООП в PHP.


Все уроки курса:


Количество уроков: 17

Продолжительность курса: 05:49:22

Автор: Андрей Кудлай

Меня зовут Андрей Кудлай — один из авторов проекта webformyself и практикующий веб-разработчик. Имею хорошие навыки работы с HTML, CSS, jQuery, PHP, MySQL, Bootstrap, CakePHP, Yii2, WordPress, OpenCart. Являюсь автором нескольких курсов-бестселлеров издательства WebForMySelf.com

Описание курса: В данном курсе мы рассмотрим теоретические аспекты ООП, а также научимся применять полученные знания на практике. Курс состоит из 17 уроков, в которых мы шаг за шагом изучим основы ООП, которых должно быть достаточно для написания приложений в объектном стиле.


Категории премиум

Неделя ООП – Онлайн-интенсив по объектно-ориентированному программированию

Неделя ООП – Онлайн-интенсив по объектно-ориентированному программированию

Многие просят меня обучить их какому-нибудь PHP-фреймворку, мотивируя это тем, что хотят перейти на новый уровень разработки. Но после собеседования часто оказывается, что они работали только с самописным кодом или с процедурными CMS, где толком не встречались с объектно-ориентированным подходом:

Без знаний ООП изучать какой-либо фреймворк нет смысла. Поэтому решил провести отдельный интенсив по ООП на основе материала со своих уроков, дополнив новыми разделами про лучшие практики разработки и практическими примерами, чего порой не хватает во многих теоретических курсах.

Для кого этот интенсив?

Получите море пользы, если Вы:
  • Слышали об ООП, но так и не осилили изучить
  • Застряли на процедурном программировании
  • Хотите изучить какой-нибудь ООП-фреймворк
  • Не знаете, чем класс отличается от интерфейса
  • Хотите ознакомиться с хорошими практиками
  • Хотите разрабатывать удобные программы
  • Откладывали изучение ООП до сегодняшнего дня
Бессмыcленно проходить курс, если Вы:
  • Уже и так всё это знаете
  • Считаете, что перенеся процедуры в класс получите объект
  • Не собираетесь переходить на фреймворки
  • Не верите что в курсах есть что-то интересное
  • Считаете что купив курс, в тот же миг всему научитесь
  • Хотите отложить изучение ещё на пару лет
  • Да и вообще, если во всём сомневаетесь

Присоединяйтесь, если Вы:

  • Не хотите стать типичным «пэхапешником», над которыми часто смеются.
  • Хотите допускать меньше ошибок в своём коде и уметь их находить.
  • Хотите уметь держать сложность проекта под контролем, а не пускать его на самотёк.
  • Стремитесь к повышению эстетического и технического качества кода.
  • Собираетесь разрабатывать сложные проекты.
  • Хотите больше думать о полезном коде, а не тратить кучу времени на рутину.
  • Желаете знать сильные и слабые стороны фреймворков.
  • Хотите научиться более качественно анализировать задачи.
  • Хотите создавать легкотестируемый программный код.
  • Хотите уметь понимать чужой код.
  • Интересуетесь принципами и практиками программной архитектуры.
  • Хотите провести этот месяц с пользой.
  • Хотите понимать суть вопросов, которые Вам задают на собеседовании.

Автор: Дмитрий Елисеев

Программист с 2008 года.
Специализируется на теории и практике бэкенд-разработки.
Автор блога и ведущий вебинаров по веб-программированию.

Формат участия

  • После заказа Вам предоставят доступ к личному кабинету ученика с записями всех уроков.
  • Уроки были записаны в виде вебинаров-скринкастов с демонстрацией экрана и общением в чате.
  • По любым техническим вопросом Вам будет дан ответ в службе поддержки.

Программа интенсива

За эти шесть насыщенных вечеров мы с вами:

  • Узнаем, кому нужен ООП и кому не нужен.
  • Научимся моделировать предметную область и разбивать сложную логику на объекты.
  • Научимся использовать «чистое» ООП и узнаем, чем оно полезно.
  • Разберёмся, что же такое «Модель» в MVC.
  • Ответим на вопрос, куда же деть бизнес-логику.
  • Узнаем, как делать «тонкие контроллеры».
  • Рассмотрим лучшие практики и принципы функционального программирования, применимые в ООП.
  • Изучим основополагающие архитектурные принципы и паттерны.
  • Научимся пользоваться Dependency Injection контейнерами: независимыми и встроенными в популярные фреймворки.
  • Научимся писать понятный и тестируемый код, модульные тесты с PHPUnit.
  • Узнаем нюансы написания легкотестируемого кода.
  • Научимся писать фреймворконезависимый переносимый код, полюбим интерфейсы.
  • Изучим устройство нескольких популярных высококачественных компонентов.
  • Научимся активно использовать Composer для подключения пакетов.
  • Научимся самостоятельно создавать гибкие и переносимые компоненты, чтобы экономить своё время.
  • Напишем полноценное приложение на фреймворке.

Расписание

День первый

Философия: Что это, как и для чего

  • Какие парадигмы программирования бывают
  • Отход от процедурного программирования к ООП
  • Кому и как объекты упрощают жизнь, а кому усложняют
  • Как придумывали объектно-ориентированную парадигму
  • Чем удобнее пользовательские типы и структуры данных
  • Динамическая память, указатели и сборщик мусора
  • Передача по ссылке и по значению

День второй

Теория: Как пишутся классы

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

День третий

Принципы: Как пишутся хорошие классы

  • Мышление ООПэшного программиста
  • Почему неООПэшника сразу видно
  • Чем же абстрактный класс отличается от интерфейса
  • Наследуемся грамотно, избегая хаоса
  • Инкапсуляция и полиморфизм на примере
  • Использование принципов по-полной
  • Слова, которые все говорят, но лишь единицы понимают

День четвёртый

Принципы: Как пишутся хорошие программы

  • Написание понятного кода
  • Для чего нам нужен рефакторинг
  • ООП для укрощения сложности
  • Скажем дружно «нет лапшекоду»
  • Какие принципы проектирования существуют
  • Какие качества в себе нужно воспитать
  • Так ли это всё в реальной жизни

День пятый

Свойства, методы, события, исключения

  • Как не превратить проект в хаос
  • Взгляд на объект со стороны
  • Давать ли прямой доступ к свойствам
  • Создание и обработка событий (Event)
  • Использование исключений (Exception)
  • Делаем однонаправленные зависимости
  • Связи между уровнями абстракции

День шестой

Практика: Как мы напишем программу

На основе изученных подходов и принципов придумываем автоматизацию отдела кадров типового бизнеса: как спрограммировать приём сотрудников на работу и отправку в отпуск, чтобы все были довольны.

Здесь подробно обсудим:

  • Что важно для заказчика
  • Что важно для программиста
  • Плюсы и минусы ActiveRecord и CRUD
  • Куда поместить бизнес-логику… и прочие вещи

Радченко Глеб Игоревич



Научные интересы

  • Грид-вычисления.
  • Облачные вычисления.
  • Распределенные вычислительные системы.

Публикации

Проекты

  1. Проект Erasmus+ [email protected] Основная цель проекта [email protected] – поддержка развития, модернизации, интернационализации высшего образования, а именно исследовательской составляющей европейского образования уровня PhD, содействие созданию новых PhD-программ в странах-партнерах в области программной инженерии.
  2. Сервисно-ориентированный подход к использованию проблемно-ориентированных пакетов в распределенных и грид-средах (проект DiVTB).
  3. Параллельная реализация нейросетевого алгоритма распознавания раздельной речи (Часть 1, Часть 2, Часть 3).

Новости

  • [2013-12-25]  Обновления страниц курсов:
  • [2013-12-17]  Обновления страниц курсов:
  • [2013-11-28]  Обновления страниц курсов:

 

  • [2013-11-07]  Размещены слайды презентаций:
  • [2013-10-26] Размещены слайды презентаций:
  • [2013-06-03]  Размещены слайды презентаций:

[Архив новостей]

Ссылки

  • Mendeley — система для каталогизации и управления библиографией. Встраивается в Microsoft Word, позволяя автоматизировать процесс управления списками литературы при подготовке статей. Поддерживает множество форматов оформления библиографических ссылок, включая ГОСТ-7.0.5-2008.
  • Memsource — операционная среда для выполнения письменных переводов, включающая базы памяти переводов, встроенный машинный перевод, модуль управления терминологией, а также текстовый редактор MemSource Editor. Может импортировать и экспортировать документы всех стандартных форматов, включая Word и PowerPoint.

Мой профиль

 

Что такое объектно-ориентированное программирование? Подробное объяснение ООП

Примечание. Родительский класс также известен как суперкласс или базовый класс. Дочерний класс также можно назвать производным классом или расширенным классом.

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

Это та же концепция, что и наследование родитель / потомок. Наследование осуществляется от родителя к ребенку. В нашем примере все три собаки могут лаять, но только Майзель и Пушистый могут пасти стадо.

Метод herding () определен в дочернем классе HerdingDog , поэтому два объекта, Maisel и Fluffy , экземпляры которых созданы из класса HerdingDog , имеют доступ к методу herding () .

Rufus — это объект, созданный из родительского класса Dog , поэтому Rufus имеет доступ только к методу bark () .

Объект Создан из класса Родительский класс Методы
Руфус Собака НЕТ кора ()
Майзель Пастушья собака Собака кора (), стадо ()
Пушистый Пастушья собака Собака кора (), стадо ()

Инкапсуляция

Инкапсуляция означает размещение всей важной информации внутри объекта и предоставление только избранной информации внешнему миру.Атрибуты и поведение определяются кодом внутри шаблона класса.

Затем, когда объект создается из класса, данные и методы инкапсулируются в этот объект. Инкапсуляция скрывает реализацию внутреннего программного кода внутри класса и скрывает внутренние данные внутренних объектов.

Инкапсуляция требует определения некоторых полей как частных, а некоторых как общедоступных.

  • Частный / внутренний интерфейс: методов и свойств, доступных из других методов того же класса.
  • Открытый / внешний интерфейс: методов и свойств, доступных также извне класса.

Давайте использовать автомобиль в качестве метафоры для инкапсуляции. Информация, которую автомобиль передает внешнему миру, используя указатели поворота для указания поворота, является общедоступным интерфейсом. Напротив, двигатель спрятан под капотом.

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

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

O bject- o riented p rogramming ( OOP ) относится к типу компьютерного программирования (разработка программного обеспечения), в котором программисты определяют тип данных структуры данных, а также типы операций. (функции), которые можно применить к структуре данных.

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

Основные концепции ООП

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

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

Преимущества объектно-ориентированного программирования

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

OOPL — языки объектно-ориентированного программирования

An o bject- o riented p rogramming l anguage ( OOPL ) — это язык программирования высокого уровня, основанный на объектно-ориентированной модели. Для выполнения объектно-ориентированного программирования необходим объектно-ориентированный язык программирования.Многие современные языки программирования являются объектно-ориентированными, однако некоторые старые языки программирования, такие как Паскаль, предлагают объектно-ориентированные версии. Примеры объектно-ориентированных языков программирования включают Java, C ++ и Smalltalk.

Первое ООПЛ

Simula, разработанный в 1960-х годах в Норвежском вычислительном центре в Осло, считается первым объектно-ориентированным языком программирования. Несмотря на то, что он является первым, Smaslltalk считается единственной настоящей объектно-ориентированной средой программирования, с которой следует сравнивать все остальные.Впервые он был разработан для использования в образовательных целях в исследовательском центре Xerox Corporation в Пало-Альто в конце 1960-х годов и выпущен в 1972 году.

Рекомендуемая литература: Учебные пособия Webopedia — Основы Java: переменные, синтаксис и соглашения и основы Java, часть 2: Операторы, модификаторы и структуры.

Определение объектно-ориентированного программирования | PCMag

Структура языка программирования, в которой данные и связанная с ними обработка («методы») определены как автономные сущности, называемые «объектами».«Сегодняшняя норма — языки объектно-ориентированного программирования (ООП), такие как C ++ и Java, предоставляют формальный набор правил для создания и управления объектами. Данные хранятся в традиционной реляционной базе данных или в базе данных объектов, если данные имеют сложная структура. См. сопоставление OR и объектную базу данных.

В объектно-ориентированном программировании есть три основных особенности, которые отличает их от языков, отличных от ООП: инкапсуляция, наследование и полиморфизм.

Инкапсуляция обеспечивает модульность
Инкапсуляция относится к создание автономных модулей, которые связывают функции обработки с данными.Эти определяемые пользователем типы данных называются «классами», а один экземпляр класса является «объектом». Например, в системе расчета заработной платы классом может быть Manager, а Pat и Jan могут быть двумя экземплярами (двумя объектами) класса Manager. Инкапсуляция обеспечивает хорошую модульность кода, при которой подпрограммы разделены и менее подвержены конфликтам друг с другом.

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

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

Языки ООП
Используемый для моделирования поведения системы в конце 1960-х годов, SIMULA был первым объектно-ориентированным языком. В 1970-х Smalltalk от Xerox был первым объектно-ориентированным языком программирования, который использовался для создания графического пользовательского интерфейса (см. Xerox Star).ACTOR и Eiffel также раньше были языками ООП.

Сегодня популярными объектно-ориентированными языками являются C ++, C #, Java, JavaScript, Visual Basic.NET и Python. Ниже приводится сравнение основных терминов ООП с традиционным программированием. См. Объектно-ориентированную СУБД.

  ООП Традиционное программирование 

 класс определить данные + обработка

 данные объекта + обработка

 данные атрибута (поле)

 функция метода

 вызов функции сообщения

 создать экземпляр создать структуру
 

Соотношение vs.Моделирование объектов

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

Как объяснить концепции объектно-ориентированного программирования шестилетнему ребенку

Александра Петкова

Вы замечали, что одни и те же клише вопросы всегда задаются на собеседовании — снова и снова?

Я уверен, вы понимаете, о чем я.

Например:

Где вы видите себя через пять лет?

или, что еще хуже:

Что вы считаете своей самой большой слабостью?

Ух… дай мне передохнуть. Считаю ответ на этот вопрос большой слабостью! Во всяком случае, я не о том.

Какими бы тривиальными ни были подобные вопросы, они важны, потому что они дают подсказку о вас. Ваше текущее состояние ума, ваше отношение, ваша точка зрения.

Отвечая, будьте осторожны, так как вы можете раскрыть то, о чем позже пожалеете.

Сегодня я хочу поговорить о подобном типе вопросов в мире программирования:

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

Я был по обе стороны этого вопроса. Это одна из тех тем, которые задают так часто, что вы не можете позволить себе не знать.

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

  1. Подготовился ли кандидат к этому собеседованию?
    Бонусные баллы, если ответ услышишь сразу — это серьезный подход.
  2. Кандидат прошел этап обучения?
    Понимание принципов объектно-ориентированного программирования (ООП) показывает, что вы вышли за рамки копирования и вставки из руководств — вы уже видите вещи с более высокой точки зрения.
  3. Понимание кандидата глубокое или поверхностное?
    Уровень компетенции по этому вопросу часто равен уровню компетенции по большинству других предметов . Поверьте мне.
Как выглядит разработчик начального уровня после ответа на этот вопрос!

Четыре принципа объектно-ориентированного программирования: инкапсуляция , абстракция , наследование , и полиморфизм .

Эти слова могут показаться пугающими для начинающего разработчика. А сложные, чрезмерно длинные объяснения в Википедии иногда удваивают путаницу.

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

Инкапсуляция

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

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

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

Допустим, мы создаем крошечную игру Sims.Есть люди и есть кошка. Они общаются друг с другом. Мы хотим применить инкапсуляцию, поэтому мы инкапсулируем всю логику «cat» в класс Cat . Это может выглядеть так:

Кошку можно покормить. Но вы не можете напрямую изменить степень голода кошки.

Здесь «состояние» кота — это частных переменных настроение , голод и энергия . Он также имеет частный метод meow () . Он может вызывать его, когда хочет, другие классы не могут сказать кошке, когда мяукать.

То, что они могут делать, определено в публичных методах sleep () , play () и feed () . Каждый из них каким-то образом изменяет внутреннее состояние и может вызывать meow () . Таким образом, выполняется привязка между частным состоянием и общедоступными методами.

Это инкапсуляция.

Абстракция

Абстракцию можно рассматривать как естественное расширение инкапсуляции.

В объектно-ориентированном дизайне программы часто бывают очень большими.А отдельные объекты много общаются друг с другом. Так что поддерживать такую ​​большую кодовую базу в течение многих лет — с постоянными изменениями — сложно.

Абстракция — это концепция, призванная облегчить эту проблему.

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

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

Думаю — кофеварка.Он много чего делает и издает причудливые звуки под капотом. Но все, что вам нужно сделать, это налить кофе и нажать кнопку.

Желательно, чтобы этот механизм был простым в использовании и редко менялся с течением времени. Думайте об этом как о небольшом наборе общедоступных методов, которые любой другой класс может вызывать, не «зная», как они работают.

Еще один реальный пример абстракции?
Подумайте о том, как вы используете свой телефон:

Сотовые телефоны сложны. Но пользоваться ими просто.

Вы взаимодействуете со своим телефоном, используя всего несколько кнопок.Что происходит под капотом? Вам не обязательно знать — детали реализации скрыты. Вам нужно знать лишь небольшой набор действий.

Изменения реализации — например, обновление программного обеспечения — редко влияют на используемую вами абстракцию.

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

Хорошо, мы увидели, как инкапсуляция и абстракция могут помочь нам разработать и поддерживать большую кодовую базу.

Но знаете ли вы, что является еще одной распространенной проблемой в дизайне ООП?

Объекты часто очень похожи. У них общая логика.Но они не совсем те же . Ух…

Так как же нам повторно использовать общую логику и выделить уникальную логику в отдельный класс? Один из способов добиться этого — наследование.

Это означает, что вы создаете (дочерний) класс, производя его от другого (родительского) класса. Таким образом, мы формируем иерархию.

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

Например:

Частный учитель — это тип учителя.А любой учитель — это тип Человека.

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

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

Полиморфизм

Мы подошли к самому сложному слову! Полиморфизм в переводе с греческого означает «множество форм».

Итак, мы уже знаем силу наследования и с радостью ею пользуемся.Но возникает такая проблема.

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

Это можно решить с помощью полиморфизма.

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

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

Каждый раз, когда коллекция (например, список) или метод ожидает экземпляр родительского объекта (где описаны общие методы), язык заботится об оценке правильной реализации общего метода — независимо от того, какой дочерний элемент передан.

Взгляните на эскиз реализации геометрических фигур. Они повторно используют общий интерфейс для вычисления площади поверхности и периметра:

Треугольник, Круг и Прямоугольник теперь можно использовать в одной коллекции

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

Затем, если этот список пытается вычислить поверхность для элемента, правильный метод будет найден и выполнен.Если элемент является треугольником, вызывается функция треугольника CalculateSurface () . Если это круг, то вызывается функция круга CalculateSurface () . И так далее.

Если у вас есть функция, которая работает с фигурой, используя ее параметр, вам не нужно определять ее три раза — один раз для треугольника, круга и прямоугольника.

Вы можете определить его один раз и принять в качестве аргумента фигуру . Передаете ли вы треугольник, круг или прямоугольник — если они реализуют CalculateParamter () , их тип не имеет значения.

Надеюсь, это помогло. Вы можете напрямую использовать те же самые объяснения на собеседовании.

Если вам что-то все еще сложно понять — не стесняйтесь спрашивать в комментариях ниже.

Что дальше?

Быть готовым ответить на один из самых популярных вопросов на собеседовании — это здорово, но иногда вас никогда не вызывают на собеседование.

Далее я сосредоточусь на том, что работодатели хотят видеть в младшем разработчике и как выделиться из толпы при поиске работы.

Следите за обновлениями.

Понравилось прочитанное? Если вы хотите поддержать меня, вы можете купить мне кофе 🙂

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

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

Прежде чем углубиться в четыре столпа ООП, я хотел бы остановиться на некоторых основных терминологиях.

Объект : экземпляр класса / рабочий объект класса

Класс : это модель или стандарт возможностей того, что объект может делать

Метод: Может изменять состояние класса, которое будет применяться ко всем экземплярам класса

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

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

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

Инкапсуляция

Инкапсуляция выполняется, когда каждый объект поддерживает частное состояние внутри класса. Другие объекты не могут напрямую обращаться к этому состоянию, вместо этого они могут вызывать только список общедоступных функций.Объект управляет своим собственным состоянием с помощью этих функций, и никакой другой класс не может его изменить, если это явно не разрешено. Чтобы общаться с объектом, вам нужно будет использовать предоставленные методы. Мне нравится думать об инкапсуляции на примере людей и их собак. Если мы хотим применить инкапсуляцию, мы делаем это, инкапсулируя всю «собачью» логику в класс Dog. «Состояние» собаки находится в частных переменных: игривость, голод и энергия, и каждая из этих переменных имеет свои соответствующие поля.

Существует также частный метод: bark (). Класс собак может вызывать это, когда захочет, а другие классы не могут сказать собаке, когда лаять. Существуют также общедоступные методы, такие как sleep (), play () и eat (), которые доступны другим классам. Каждая из этих функций изменяет внутреннее состояние класса Dog и может вызывать bark (), когда это происходит, частное состояние и общедоступные методы связываются.

Абстракция

Абстракция — это расширение инкапсуляции.Это процесс выбора данных из большего пула, чтобы показать объекту только релевантные детали. Предположим, вы хотите создать приложение для знакомств, и вас просят собрать всю информацию о ваших пользователях. Вы можете получить от своего пользователя следующие данные: полное имя, адрес, номер телефона, любимую еду, любимый фильм, хобби, налоговую информацию, номер социального страхования, кредитный рейтинг. Этот объем данных велик, однако не все они необходимы для создания профиля знакомств. Вам нужно только выбрать из этого пула информацию, имеющую отношение к вашему приложению для знакомств.Такие данные, как полное имя, любимая еда, любимый фильм и хобби, имеют смысл для приложения для знакомств. Процесс получения / удаления / выбора информации о пользователе из большего пула называется абстракцией. Одним из преимуществ Abstraction является возможность применять ту же информацию, которую вы использовали для приложения знакомств, к другим приложениям с небольшими изменениями или без них.

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

Наследование — это способность одного объекта приобретать некоторые / все свойства другого объекта.Например, ребенок наследует черты своих родителей. При наследовании возможность многократного использования является большим преимуществом. Вы можете повторно использовать поля и методы существующего класса. В Java существуют различные типы наследования: одиночное, множественное, многоуровневое, иерархическое и гибридное. Например, Apple — это фрукт, поэтому предположим, что у нас есть класс Fruit и его подкласс с именем Apple. Наше яблоко приобретает свойства класса Fruit. Другими классификациями могут быть виноград, груша, манго и т. Д. Фрукты определяют класс продуктов, которые представляют собой зрелые завязи растения, мясистые, содержащие большое семя внутри или множество крошечных семян.Подкласс Apple приобретает эти свойства от Fruit и обладает некоторыми уникальными свойствами, которые отличаются от других подклассов Fruit, таких как красный, круглый, выемчатый наверху.

Полиморфизм

Полиморфизм дает нам возможность использовать класс точно так же, как его родительский, поэтому нет путаницы со смешением типов. При этом каждый дочерний подкласс сохраняет свои собственные функции / методы такими, какие они есть. Если бы у нас был суперкласс Mammal, в котором есть метод mammalSound ().Подклассами млекопитающих могут быть собаки, киты, слоны и лошади. У каждого из них будет своя собственная итерация звука млекопитающего (лай собаки, щелчок кита).

ПОДРОБНЕЕ: Основы между GraphQL и REST API, Прототипирование и исследование UX, Диаграммы сходства и кластеризация, Создание пользовательского пользовательского интерфейса материала: Создание цветовой схемы

Если все это ненавидят, почему ООП все еще так широко распространено?

В августовском выпуске журнала Byte за 1981 г. Дэвид Робсон открывает свою статью, ставшую для многих введением в «объектно-ориентированные программные системы», сразу признавая, что это отход от того, что многие знакомы с императивом. вниз привыкли к программированию.

«Многие люди, не имеющие представления о том, как работает компьютер, находят идею объектно-ориентированного программирования вполне естественной. Напротив, многие люди, имеющие опыт работы с компьютерами, сначала думают, что в объектно-ориентированных системах есть что-то странное ».

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

Некоторые утверждали, что при ООП писать тесты сложнее и требует особого внимания при рефакторинге.При повторном использовании кода возникают накладные расходы, которые создатель Erlang, как известно, описал как случай, когда вы хотели банан, но у вас есть горилла, держащая банан. У всего есть неявная, неизбежная среда.

Другие способы описания этого нового способа решения проблем включают аналогию между императивным программистом как «повар или химик, следуя рецептам и формулам для достижения желаемого результата» и объектно-ориентированным программистом как «греческий философ или натуралист XIX века». занимается правильной систематизацией и описанием существ и мест в мире программирования.”

Успех был просто совпадением?

ООП по-прежнему остается одной из доминирующих парадигм. Но это может быть связано с успехом языков, которые оказываются ООП. Java, C ++ и Kotlin управляют мобильными устройствами для Android и Swift и Objective-C для iOS, поэтому вы не сможете разрабатывать программное обеспечение для мобильных устройств, если не понимаете объектно-ориентированный подход. Для Интернета это JavaScript, Python, PHP и Ruby.

Спрашивать, почему так много широко используемых языков являются ООП, можно путать причину и следствие.Ричард Фельдман в своем выступлении утверждает, что это могло быть просто совпадением. C ++ был разработан в начале 1980-х Бьярном Страуструпом, первоначально как набор расширений языка программирования C. Основываясь на C, C ++ добавил объектную ориентацию, но Фельдман утверждает, что он стал популярным благодаря общему обновлению с C, включая безопасность типов и добавленную поддержку автоматического управления ресурсами, общего программирования и обработки исключений, среди других функций.

Затем Java захотела обратиться к программистам на C ++ и удвоила объем ООП.В конечном итоге Sun Microsystems захотела повторить трюк с C ++, стремясь сделать его максимально понятным для разработчиков, внедряющих Java.

Миллионы разработчиков быстро перешли на Java из-за ее исключительной интеграции в веб-браузеры в то время. С этой точки зрения ООП, кажется, просто увлекает, а не способствует успеху.

Что уникального может делать ООП?

У ООП есть несколько ценных аспектов, некоторые из которых делают его вездесущим, даже если у него есть свои недостатки.Давайте посмотрим на краеугольные камни ООП.

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

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

Наследование . Поскольку объекты могут быть созданы как подтипы других объектов, они могут наследовать переменные и методы этих объектов. Это позволяет объектам поддерживать операции, определенные предшествующими типами, без необходимости предоставлять собственное определение. Цель состоит в том, чтобы не повторяться — сложно поддерживать многократное использование одного и того же кода. Но функциональное программирование может также достичь СУХОГО за счет функций многократного использования. То же самое и с эффективностью памяти. Несмотря на то, что наследование действительно способствует этому, концепция замыканий в FP тоже вносит свой вклад.

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

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

Похоже, что в 2020 году ООП не сможет сделать так много, что другие парадигмы программирования не могут, и хороший программист будет использовать стратегии из нескольких парадигм вместе в борьбе со сложностью. Например, если вы посмотрите на теги, которые чаще всего появляются в связи с вопросом, помеченным в разделе «ООП против функционального программирования», в обоих случаях появляется JavaScript.

Что нас ждет? Однако

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

Так что же сами разработчики? Наш опрос разработчиков в этом году показывает, что они приобретают все больше и больше покупательского влияния. Что ж, если мы также посмотрим на то, с чем предпочитают работать разработчики, Haskell и Scala — одни из самых любимых языков программирования. Scala дает вам вторую по величине зарплату.Так что, возможно, с большим количеством проповедей FP, они тоже поднимутся в списке самых популярных языков.

Есть некоторое движение, большие компании, такие как Twitter, почти полностью используют свой бэкэнд на коде Scala. Facebook, который недавно применял Haskell и многие из основных языков ООП, также принимает функциональные возможности. В .NET есть LINQ, а в Java 8 появились Lambdas. JavaScript становится все более функциональным, несмотря на введение классов в ES6. Swift может быть золотой серединой между объектно-ориентированным и функциональным языками.Так что, возможно, нет необходимости выбирать: у вас тоже может быть торт класса и EatCake () .


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

Теги: функциональное программирование, объектно-ориентированное программирование, oop

Объектно-ориентированное программирование на C ++

СОДЕРЖАНИЕ :

  1. Введение
  2. Класс
  3. Объекты
  4. Инкапсуляция
  5. Абстракция
  6. Полиморфизм
  7. Наследование
  8. Связывание
  9. Передача сообщения

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

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

Класс : Строительный блок C ++, который ведет к объектно-ориентированному программированию, — это класс.Это определяемый пользователем тип данных, который содержит свои собственные элементы данных и функции-члены, к которым можно получить доступ и использовать, создав экземпляр этого класса. Класс подобен проекту объекта.


Например: рассмотрим класс автомобилей. Может быть много автомобилей с разными названиями и марками, но все они будут иметь некоторые общие свойства, например, все они будут иметь 4 колеса, ограничение скорости, диапазон пробега и т. Д. Итак, здесь Car — это класс, а колеса, ограничения скорости, пробег — это их свойства.

  • Класс — это определяемый пользователем тип данных, который имеет элементы данных и функции-члены.
  • Элементы данных — это переменные данных, а функции-члены — это функции, используемые для управления этими переменными, и вместе эти элементы данных и функции-члены определяют свойства и поведение объектов в классе.
  • В приведенном выше примере класса Car элементом данных будет ограничение скорости, пробег и т. Д., А функции-члены могут применять тормоза, увеличивать скорость и т. Д.

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

Объект: Объект — это идентифицируемый объект с некоторыми характеристиками и поведением. Объект — это экземпляр класса. Когда класс определен, память не выделяется, но когда он создается (т. Е. Создается объект), выделяется память.

класс человек

{

символ имя [20];

внутр id;

общедоступный :

void getdetails () {}

};

int main ()

{

человек p1;

}


Объект занимает место в памяти и имеет связанный адрес, такой как запись в паскале, структура или объединение в C.

Когда программа выполняется, объекты взаимодействуют, отправляя сообщения друг другу.

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

Инкапсуляция : Обычно инкапсуляция определяется как объединение данных и информации в один блок. В объектно-ориентированном программировании инкапсуляция определяется как связывание данных и функций, которые ими управляют.

Рассмотрим реальный пример инкапсуляции. В компании есть различные разделы, такие как раздел счетов, финансовый раздел, раздел продаж и т. Д. Финансовый раздел обрабатывает все финансовые транзакции и хранит записи всех данных, связанных с финансами. Точно так же отдел продаж обрабатывает все операции, связанные с продажами, и ведет учет всех продаж. Теперь может возникнуть ситуация, когда чиновнику из финансового отдела по каким-то причинам понадобятся все данные о продажах за конкретный месяц.В этом случае ему не разрешен прямой доступ к данным раздела продаж. Сначала ему нужно будет связаться с другим сотрудником отдела продаж, а затем попросить его предоставить конкретные данные. Вот что такое инкапсуляция. Здесь данные отдела продаж и сотрудники, которые могут ими манипулировать, объединены под одним названием «отдел продаж».



Инкапсуляция в C ++

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

Абстракция : Абстракция данных — одна из наиболее существенных и важных функций объектно-ориентированного программирования на C ++. Абстракция означает отображение только важной информации и скрытие деталей. Абстракция данных относится к предоставлению только важной информации о данных внешнему миру, скрывая фоновые детали или реализацию.

Рассмотрим пример из реальной жизни человека, управляющего автомобилем.Человек знает только, что нажатие на педаль акселератора увеличит скорость автомобиля или нажатие на педаль тормоза остановит машину, но он не знает, как на самом деле увеличивается скорость при нажатии на педаль акселератора, он не знает о внутреннем механизме автомобиля или внедрение в автомобиль акселератора, тормозов и т. д. Вот что такое абстракция.

  • Абстракция с использованием классов : Мы можем реализовать абстракцию на C ++ с помощью классов. Класс помогает нам группировать элементы данных и функции-члены с помощью доступных спецификаторов доступа.Класс может решить, какой член данных будет виден внешнему миру, а какой нет.
  • Абстракция в файлах заголовков : Еще одним типом абстракции в C ++ могут быть файлы заголовков. Например, рассмотрим метод pow (), присутствующий в заголовочном файле math.h. Всякий раз, когда нам нужно вычислить мощность числа, мы просто вызываем функцию pow (), присутствующую в файле заголовка math.h, и передаем числа в качестве аргументов, не зная базового алгоритма, согласно которому функция фактически вычисляет мощность чисел. .

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

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

В разных случаях операция может вести себя по-разному.Поведение зависит от типов данных, используемых в операции.

C ++ поддерживает перегрузку операторов и функций.

  • Перегрузка оператора : Процесс, при котором оператор демонстрирует различное поведение в разных случаях, известен как перегрузка оператора.
  • Перегрузка функций : Перегрузка функций использует одно имя функции для выполнения различных типов задач.
    Полиморфизм широко используется при реализации наследования.

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

Наследование : способность класса извлекать свойства и характеристики из другого класса называется наследованием. Наследование — одна из важнейших функций объектно-ориентированного программирования.

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

Пример : Собака, кошка, корова могут быть производным классом от базового класса животных.

Динамическое связывание: При динамическом связывании код, который будет выполняться в ответ на вызов функции, определяется во время выполнения. В C ++ есть виртуальные функции для поддержки этого.


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

Оставить комментарий

Добавить комментарий

Ваш адрес email не будет опубликован.