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

Полиморфизм

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

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

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

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

Понятие «объект» в ООП

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

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

  • каждое свойство состоит из имени и значения, ассоциированного с этим именем;
  • значением свойства может быть функция, которую можно назвать методом объекта. 

Свойства объекта в JavaScript

В JavaScript объект имеет свойства, ассоциированные с ним. Свойство объекта:

  • можно понимать как переменную, закрепленную за объектом;
  • определяют характеристики объекта.

Получение доступа к свойству объекта:

JavaScript

objectName.propertyName
// или
objectName

1
2
3

objectName.propertyName

// или

objectName»propertyName»

Примеры:

JavaScript

var myCar = new Object(); // создание объекта с помощью конструктора
myCar.make = «Ford»;
myCar.model = «Mustang»;
myCar.year = 1969;

// или
myCar = «Ford»;
myCar = «Mustang»;
myCar = 1969;

1
2
3
4
5
6
7
8
9

varmyCar=newObject();// создание объекта с помощью конструктора

myCar.make=»Ford»;

myCar.model=»Mustang»;

myCar.year=1969;

 
// или

myCar»make»=»Ford»;

myCar»model»=»Mustang»;

myCar»year»=1969;

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

Примеры

JavaScript

var myObj = new Object(),
str = «myString»,
rand = Math.random(),
obj = new Object();

myObj.type = «Dot syntax»;
myObj = «String with space»;
myObj = «String value»;
myObj = «Random Number»;
myObj = «Object»;
myObj = «Even an empty string»;

console.log(myObj);

1
2
3
4
5
6
7
8
9
10
11
12
13

varmyObj=newObject(),

str=»myString»,

rand=Math.random(),

obj=newObject();

myObj.type=»Dot syntax»;

myObj»date created»=»String with space»;

myObjstr=»String value»;

myObjrand=»Random Number»;

myObjobj=»Object»;

myObj»»=»Even an empty string»;

console.log(myObj);

Обратите внимание, что все ключи с квадратными скобками преобразуются в тип String, поскольку объекты в JavaScript могут иметь в качестве ключа только тип String. Например, в приведенном выше коде, когда ключ obj добавляется в myObj, JavaScript вызывает метод obj.toString () и использует эту результирующую строку в качестве нового ключа

Класс

Классы, в некотором смысле, подобны чертежам: это не объекты сами по себе, а их схемы. Класс «банковских счетов» имеет строго определенные и одинаковые для всех атрибуты, но объекты в нём – сами счета – уникальны.

Как в Python создать класс

В Python классы и объекты по смыслу не отличаются от других языков. Нюансы в реализации. Для создания класса в Питоне необходимо написать инструкцию , а затем выбрать имя. В простейшем случае, класс выглядит так:

Для именования классов в Python обычно используют стиль «camel case», где первая буква – заглавная.

Конструктор

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

В качестве Питоновского конструктора выступает метод

Атрибуты класса

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

Поля могут быть статическими и динамическими:

  • Статические поля (поля класса) можно использовать без создания объекта. А значит, конструктор вам не нужен.
  • Динамические поля (поля объекта) задаются с помощью конструктора, и тут уже, как вы видели, экземпляр нужно создать, а полям присвоить значения.

️ Обратите внимание – статический и динамический атрибут может иметь одно и то же имя:

Методы класса

Метод – это функция класса.

Например, у всех научно-фантастических космических кораблей есть бортовое оружие. И оно может стрелять.

Что такое self?

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

Отличный пример с котофеями:

  1. Все котики умеют мурлыкать;
  2. Эта способность реализована в классе , как метод ;
  3. Вы хотите, чтобы ваш кот по имени Пушок помурчал;
  4. Если сделать так: , то мурлыкать начнут все коты во Вселенной;
  5. Но так как вам нужен один конкретный кот, то нужно вызвать метод иначе: ;
  6. Сделано. Пушок мурлыкает.

Уровни доступа атрибутов и методов

В Питоне не существует квалификаторов доступа к полям класса. Отсутствие аналогов связки public/private/protected можно рассматривать как упущение со стороны принципа инкапсуляции.

Декораторы

Декоратор – это функция-обёртка. В неё можно завернуть другой метод, и, тем самым, изменить его функциональность, не меняя код.

Роль инкапсуляции

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

Т.е. инкапсуляция представляет собой способности языка скрывать излишние детали реализации от пользователя объекта.
Например, предположим, что используется класс по имени DatabaseReader, который
имеет два главных метода: Open() и Close().

Фиктивный класс DatabaseReader инкапсулирует внутренние детали нахождения,
загрузки, манипуляций и закрытия файла данных. Программистам нравится инкапсуляция, поскольку этот принцип ООП упрощает кодирование. Нет необходимости беспокоиться о многочисленных строках кода, которые работают «за кулисами», чтобы
реализовать функционирование класса DatabaseReader. Все, что потребуется — это
создать экземпляр и отправлять ему соответствующие сообщения (например, «открыть файл по имени AutoLot.mdf, расположенный на диске С:»).

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

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

Код и данные, составляющие вместе класс, называют членами. Данные, определяемые классом, называют полями, или переменными экземпляра. А код, оперирующий
данными, содержится в функциях-членах, самым типичным представителем которых
является метод. В C# метод служит в качестве аналога подпрограммы. (К числу других
функций-членов относятся свойства, события и конструкторы.) Таким образом, методы класса содержат код, воздействующий на поля, определяемые этим классом.

Принципы ООП

Главные принципы в ООП – абстрагирование, инкапсуляция, наследование и полиморфизм.

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

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

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

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

Принципы ООП

Абстракция

Абстракция – это выделение основных, наиболее значимых характеристик объекта и игнорирование второстепенных.

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

Полиморфизм

Полиморфизм подразумевает возможность нескольких реализаций одной идеи. Простой пример: у вас есть класс «Персонаж», а у него есть метод «Атаковать». Для воина это будет означать удар мечом, для рейнджера – выстрел из лука, а для волшебника – чтение заклинания «Огненный Шар». В сущности, все эти три действия – атака, но в программном коде они будут реализованы совершенно по-разному.

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

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

Мы могли бы сделать отдельный класс «Грузовик», который является наследником «Автотранспорта». Объекты этого класса могли бы определять все прошлые атрибуты (цвет, год выпуска), но и получить новые. Для грузовиков это могли быть грузоподъёмность, снаряженная масса и наличие жилого отсека в кабине. А методом, который есть только у грузовиков, могла быть функция сцепления и отцепления прицепа.

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

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

Вы разработали для муниципальных служб класс «Квартира». У неё есть свойства вроде адреса, метража и высоты потолков. И методы, такие как получение информации о каждом из этих свойств и, главное, метод, реализующий постановку на учёт в Росреестре. Это готовая концепция, и вам не нужно чтобы кто-то мог добавлять методы «открыть дверь» и «получить место хранения денег». Это А) Небезопасно и Б) Избыточно, а также, в рамках выбранной реализации, не нужно. Работникам Росреестра не требуется заходить к вам домой, чтобы узнать высоту потолков – они пользуются только теми документами, которые вы сами им предоставили.

3 Что учить дальше?

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

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

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

3.1 Список использованных источников

  1. Рейтинг популярности языков программирования TIOBE. URL: https://tiobe.com/tiobe-index/
  2. SOLID принципы. Рефакторинг. URL: https://pro-prof.com/archives/1914
  3. Почему мне кажется, что студентов учат ООП неправильно. URL: https://habr.com/ru/post/345658/
  4. C++ Russia 2018: Фёдор Короткий, Память – идеальная абстракция. URL: https://vk.com/wall-105242702_701
  5. Мейер Б. Объектно-ориентированное конструирование программных систем. М.: Издательско-торговый дом «Русская Редакция», «Интернет-университет информационных технологий», 2005. 1232 с.: ил.
  6. Мартин Р. Чистый код. Создание, анализ и рефакторинг. Библиотека программиста. – СПб.: Питер, 2014. – 464 с.
  7. Джейсон Мак-Колм Смит Элементарные шаблоны проектирования : Пер. с англ. — М. : ООО “И.Д. Вильямс”, 2013. — 304 с.
  8. Диаграммы классов UML. URL: https://pro-prof.com/archives/3212
  9. Юнит-тестирование. Пример. Boost Unit Test. URL: https://pro-prof.com/archives/1549
  10. Э. Гамма Приемы объектно-ориентированного проектирования. Паттерны проектирования / Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес. – СПб.: Питер, 2009. – 366 с.

Что не так с процедурным программированием

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

Тут при­хо­дит продакт-менеджер и гово­рит: «Хочу, что­бы поль­зо­ва­тель точ­но знал, в чём ошиб­ка при вво­де элек­трон­но­го адре­са». Теперь вам нуж­но научить функ­цию выда­вать не про­сто true — false, а ещё и код ошиб­ки: напри­мер, если в адре­се опе­чат­ка, то код 01, если адрес спа­мер­ский — код 02 и так далее. Это неслож­но реализовать.

Вы зале­за­е­те внутрь этой функ­ции и меня­е­те её пове­де­ние: теперь она вме­сто true — false выда­ёт код ошиб­ки, а если ошиб­ки нет — пишет «ОК».

И тут ваш код лома­ет­ся: все десять мест, кото­рые ожи­да­ли от про­ве­ряль­щи­ка true или false, теперь полу­ча­ют «ОК» и из-за это­го ломаются.

Теперь вам нужно:

  • либо пере­пи­сы­вать все функ­ции, что­бы научить их пони­мать новые отве­ты про­ве­ряль­щи­ка адресов;
  • либо пере­де­лать сам про­ве­ряль­щик адре­сов, что­бы он остал­ся сов­ме­сти­мым со ста­ры­ми места­ми, но в нуж­ном вам месте как-то ещё выда­вал коды ошибок;
  • либо напи­сать новый про­ве­ряль­щик, кото­рый выда­ёт коды оши­бок, а в ста­рых местах исполь­зо­вать ста­рый проверяльщик.

Зада­ча, конеч­но, реша­е­мая за час-другой.

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

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

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

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

// Если мы хотим определить собак, кошек и птиц, и мы знаем, что у всех этих
// животных есть имена и возраст, мы должны создать суперкласс.
// СУПЕРКЛАСС
class Animal {
    private String name;
    private int age;

    public void identify() {
        System.out.println("I am an animal!");
    }

    public void rename(String newName) {
        name = newName;
    }

    public String getName() {
        return name;
    }

    public void setAge(int newAge) {
        if(newAge > 0)
            age = newAge;
    }

    public int getAge() {
        return age;
    }
}

// ПОДКЛАССЫ
class Dog extends Animal {
    public void bark() {
        System.out.println("Bark!");
    }
}

class Cat extends Animal {
    public void meow() {
        System.out.println("Meow!");
    }
}

class Bird extends Animal {
    public void chirp() {
        System.out.println("Chirp!");
    }
}

В теоретических основах ООП это означает, что каждая собака, кошка и птица (подклассы) будут иметь атрибуты имени и возраста. А также метод Identify, потому что они являются животными (принадлежат суперклассу Animal).

Абстракция, объект, класс, модули, иерархия, интерфейс, методы

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

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

Что это, из чего это состоит, что можно с этим делать и как именно? У классов и объектов есть атрибуты, данные (Data) и методы, то есть функции для управления данными

Класс – это описание объектов, представителей класса: отличительные признаки, состояния, взаимодействия. Что это, из чего это состоит, что можно с этим делать и как именно? У классов и объектов есть атрибуты, данные (Data) и методы, то есть функции для управления данными.

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

Иерархия: модули классов; базовый класс (класс описывает свойства объектов, содержит множество объектов, подклассов), производный класс (наследует свойства родительского класса и тоже содержит объекты); отдельно взятый объект (данные/Data, описывающие свойства объекта, + методы, то есть функции для работы с объектом, алгоритмы управления, действия, которые выполняет объект).

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

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

Роль полиморфизма

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

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

Рассмотрим для примера стек, т.е. область памяти, функционирующую по принципу «последним
пришел — первым обслужен». Допустим, что в программе требуются три разных типа
стеков: один — для целых значений, другой — для значений с плавающей точкой, третий — для символьных значений. В данном примере алгоритм, реализующий все эти
стеки, остается неизменным, несмотря на то, что в них сохраняются разнотипные данные. В языке, не являющемся объектно-ориентированным, для этой цели пришлось бы
создать три разных набора стековых подпрограмм с разными именами. Но благодаря
полиморфизму для реализации всех трех типов стеков в C# достаточно создать лишь один общий набор подпрограмм. Зная, как пользоваться одним стеком, вы сумеете
воспользоваться и остальными.

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

Абстракция

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

Простой пример: представьте, что мы создаём картотеку сотрудников компании. Естественно, мы вносим их основные характеристики: дату рождения, ИНН, ФИО, номер социального страхования. Разумеется, нас не интересуют ни рост, ни цвет глаз, ни длина волос. То есть мы абстрагируемся от ненужной информации.

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

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

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

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

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector