Пример объектно ориентированной программы

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

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

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

Объектно ориентированное программирование в Python за 10 минут!

‍♂️ Итак, мы — разработчики игр. Наша студия трудится над новым автосимулятором. В игре будут представлены разные виды транспорта: легковые автомобили, гоночные, грузовые и пассажирские. Все их можно описать одним словом — автотранспорт. Сделав это, мы абстрагировались от деталей и, таким образом, определили класс.

Объектом этого класса может быть, как Бьюик 1968-го года, так и грузовой Freightliner Columbia желтого цвета.

У класса есть свойства и функции (в ООП их называют методами).

  • Свойства — это характеристики, присущие данному конкретному множеству объектов.
  • Методы — те действия, которые они могут совершать.

Свойствами класса «автотранспорт» могут быть, например: год выпуска, вид и цвет. На уровне объектов это будет выглядеть так: Бьюик Электра — это объект класса «Автотранспорт» со следующими свойствами:

  • вид — легковой автомобиль;
  • цвет — чёрный;
  • год выпуска — 1968.

Можно сказать, что объект — это вполне конкретный экземпляр класса

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

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

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

Истоки ООП берут начало с 60-х годов XX века. Однако окончательное формирование основополагающих принципов и популяризацию идеи следует отнести к 80-м годам. Большой вклад внес Алан Кей.

ООП за 5 минут что такое объектно-ориентированное программирование

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

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

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

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

Программа состоит из объектов, которые действуют друг на друга с помощью методов

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

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

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

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

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

Понятия ООП: класс, объект, наследование, инкапсуляция, полиморфизм

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

Что такое класс или тип? Проведем аналогию с реальным миром. Если мы возьмем конкретный стол, то это объект, но не класс. А вот общее представление о столах, их назначении – это класс. Ему принадлежат все реальные объекты столов, какими бы они ни были.

Класс столов дает общую характеристику всем столам в мире, он их обобщает.

Читайте также:
Galileos viewer как пользоваться программой

Класс - это общее описание. Объект - это конкретная реализация.

То же самое с целыми числами в Python. Тип int – это класс целых чисел. Числа 5, 100134, -10 и т. д. – это конкретные объекты этого класса.

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

>>> a = 145 >>> b = [‘one’, ‘two’] >>> type(a) >>> type(b) >>> >>> type(int), type(list) (, ) >>> >>> import math >>> type(math)

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

Наследование, инкапсуляция, полиморфизм

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

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

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

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

Чтобы наполнить его едой, надо совершить ритуал, через элемент интерфейса под названием рот.

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

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

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

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

Полиморфизм - одноименный метод в разных классах

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

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

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

Пример объектно-ориентированной программы на Python

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

В программе определены три класса. Класс A является родительским по отношению к B и C . Последние наследуют от A поле-переменную field1 и метод make_str , который потом переопределяют.

От каждого класса мы создаем по одному объекту и присваиваем их переменным a , b , c . Метод make_str выводит на экран значения полей объекта. У объектов разных классов разный набор полей, поэтому код метода отличается.

class A: field1 = 1 def make_str(self): print(self.field1) class B(A): field2 = 2 def make_str(self): print(self.

field1, self.field2) class C(A): field3 = 3 def make_str(self): print(self.field1, self.field3) a = A() b = B() c = C() for i in (a, b, c): i.make_str()

Результат выполнения программы:

1 1 2 1 3

Практическая работа

Схема объектно-ориентированной программы

Рассмотрите схему. Подумайте над следующими вопросами:

  1. Какие фигуры на ней вы бы назвали классами, а какие – объектами? Что обозначают пунктирные линии?
  2. Может ли объект принадлежать множеству классов? Может ли у класса быть множество объектов?
  3. Звезды скорее обладают разными свойствами или разным поведением? Могут ли свойства оказывать влияние на поведение?
  4. Что могли бы обозначать стрелки?

Курс с примерами решений практических работ:
pdf-версия

X Скрыть Наверх

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

Источник: younglinux.info

Что такое ООП и с чем его едят?

Из своего опыта могу сказать, что всегда считал что понимал ООП, что же тут такого то — полиморфизм, инкапсуляция и наследование, но вот когда дошло до дела, то туговато пришлось. Хочу разложить всё по полочкам чтобы никто не наступил на мои грабли в будущем 🙂

Читайте также:
Как называются программы показывающие скорость относительно какого либо сайта

3-principa-oop

Шаг 1.

Немного теории:

Объектно-ориентированное программирование (в дальнейшем ООП) — парадигма программирования, в которой основными концепциями являются понятия объектов и классов.

В центре ООП находится понятие объекта.

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

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

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

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

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

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

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

Полиморфизм — это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.

Шаг 2.

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

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

images

Зачем же это нужно?

Думаю, вам бы не хотелось, чтобы кто-то, что-то изменял в написанной вами библиотеки.

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

Цель инкапсуляции – уйти от зависимости внешнего интерфейса класса (то, что могут использовать другие классы) от реализации. Чтобы малейшее изменение в классе не влекло за собой изменение внешнего поведения класса. Давайте рассмотрим, как ею пользоваться.

Существует 4 вида модификаторов доступа: public, protected, private и default.

Public – уровень предполагает доступ к компоненту с этим модификатором из экземпляра любого класса и любого пакета.

Protected – уровень предполагает доступ к компоненту с этим модификатором из экземпляров родного класса и классов-потомков, независимо от того, в каком пакете они находятся.

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

Private – уровень предполагает доступ к компоненту с этим модификатором только из этого класса.

public class Human

public String name; — имя, которое доступное из любого места в приложении.
protected String surname; — фамилия доступна из родного класса и потомков.
private int age; — возраст доступен только в рамках класса Human.
int birthdayYear; — хоть не указывается явный модификатор доступа, система понимает его как default, год рождения будет доступен всему пакету, в котором находится класс Human.

Для разных структурных элементов класса предусмотрена возможность применять только определенные уровни модификаторов доступа.

Для класса — только public и default.

Для атрибутов класса — все 4 вида.

Для конструкторов — все 4 вида.

Для методов — все 4 вида.

Шаг 3.

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

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

Наследование является важным, поскольку оно позволяет поддерживать концепцию иерархии классов (hierarchical classification). Применение иерархии классов делает управляемыми большие потоки информации.

Разберем этот механизм на классическом примере: Геометрические фигуры.

1

У нас есть интерфейс Figure:

public interface Figure

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

В этом классе мы реализуем все методы интерфейса Figure.

public class Figure implements devcolibri.com.oop.inheritance.interfaces.Figure — с помощью ключевого слова implements мы перенимаем методы интерфейса Figure для реализации.

И соответственно у нас есть 3 класса самих фигур, которые наследуются от класса Figure. Класс Figure является родительским классом или классом-родителем, а классы Circle, Rectungle и Triangle — являются дочерними.

public class Triangle extends devcolibri.com.oop.inheritance.Figure — это значит, что класс Triangle наследует класс Figure.

super.setColor(colour); — super модификатор, позволяющий вызывать методы из класса родителя.

Теперь каждый класс перенял свойства класса Figure. Что собственно это нам дало?

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

Наверное возник вопрос: чем же extends отличается от implements?

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

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

В дочерних классах мы можем спокойно добавлять новые интересующие нас методы. Например, мы хотим добавить в класс Triangle 2-а новых метода: flimHorizontal () и flipVertical ():

2

/** * New Method */ public void flipVertical () < >; /** * New Method */ public void flipHorizontal () < >;

Теперь эти 2-а метода принадлежат сугубо классу Triangle. Этот подход используется когда базовый класс не может решить всех проблем.

Или можно использовать другой подход, изменить или переписать методы в дочерним классе:

3

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

Но не стоит забивать этим голову!

Шаг 4.

Полиморфизм.

В более общем смысле, концепцией полиморфизма является идея “один интерфейс, множество методов“.

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

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

public class Parent < int a = 2; >public class Child extends Parent

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

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

Компилятор может опираться только на тип ссылки, с помощью которой происходит обращение к полю:

Child c = new Child(); System.out.println(c.a); // результатом будет 3 Parent p = c; System.out.println(p.a); //результатом будет 2

Обе ссылки указывают на один и тот же объект, но тип у них разный. Отсюда и результат. Объявление поля в классе-наследнике «скрыло» родительское поле.

Данное объявление так и называется – «скрывающим». Родительское поле продолжает существовать.

К нему можно обратиться явно:

class Child extends Parent < int a = 3; //скрывающее объявление int b = ((Parent)this).a; //громоздкое обращение к родительскому полю int c = super.a; //простое обращение к родительскому полю >

Переменные b и c получат значения, родительского поля a. Хотя выражение с super более простое, оно не позволит обратиться на два уровня вверх по дереву наследования.

А ведь вполне возможно, что в родительском классе это поле также было скрывающим и в родителе родителя храниться ещё одно значение.

К нему можно обратиться явным приведением, как это делается для b.

class Parent < int x = 0; public void printX() < System.out.println(x); >> class Child extends Parent

Каков будет результат для new Child.printX(); ?

Метод вызывается с помощью ссылки типа Child, но метод определен в классеParent и компилятор расценивает обращение к полю x в этом методе именно как к полю класса Parent. Результатом будет 0.

Рассмотрим случай переопределения методов:

class Parent < public int getValue() < return 0; >> class Child extends Parent < public int getValue() < return 1; >> Child c = new Child(); System.out.println(c.getValue()); // результатом будет 1 Parent p = c; System.out.println(p.getValue()); // результатом будет 1

Родительский метод полностью перекрыт.

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

Хотя старый метод снаружи недоступен, внутри класса-наследника к нему можно обратиться с помощью super.

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

Шаг 5.

Абстракция:

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

В контексте ООП абстракция — это обобщение данных и поведения для типа, находящегося выше текущего класса по иерархии.

Перемещая переменные или методы из подкласса в супер класс, вы обобщаете их. Это общие понятия, и они применимы в языке Java. Но язык добавляет также понятия абстрактных классов и абстрактных методов.

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

Например, вы можете создать класс Animal (животное). Нет смысла создавать экземпляр этого класса: на практике вам нужно будет создавать экземпляры конкретных классов, например, Dog (собака). Но все классы Animal имеют некоторые общие вещи, например, способность издавать звуки. То, что Animal может издавать звуки, еще ни о чем не говорит.

Издаваемый звук зависит от вида животного.

Как это смоделировать?

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

В иерархии могут одновременно находиться как абстрактные, так и конкретные классы.

Использование абстракции:

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

public abstract class Person < abstract void move(); abstract void talk(); >public class Adult extends Person < public Adult() < >public void move() < System.out.println(«Walked.»); >public void talk() < System.out.println(«Spoke.»); >> public class Baby extends Person < public Baby() < >public void move() < System.out.println(«Crawled.»); >public void talk() < System.out.println(«Gurgled.»); >>

Что мы сделали в приведенном выше коде?

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru