Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Статические данные и методы классов
У классов могут быть данные и методы, которые являются общими для всех
объектов класса и не различаются у разных объектов данного класса. Такие данные и
методы называются статическими.
Пример 13-1.(файл 13-1.py)
# 13-1 Статические поля и методы
class Figure:
border_color = "black" # Статическое поле
def __init__(self, type, color):
self.type = type
# Обычное (нестатическое) поле
self.color = color # Обычное (нестатическое) поле
rect = Figure("rectangle","blue")
print(rect.type) # К обычному полю обращаемся через имя объекта rect
print(rect.color) # К обычному полю обращаемся через имя объекта rect
print(Figure.border_color) # К статическому полю обращаемся через имя класса Figure
Результат:
rectangle
blue
black
Поскольку статическое поле общее для всех объектов класса, то мы обращаемся
к нему не по имени объекта rect, а по имена класса Figure.
В то же время Python не запрещает обращаться к статическим полям через имя
объекта. Если мы выполним оператор,
print(rect.border_color)
,то ошибки не будет.
1
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Если же обратиться к обычным (нестатическим) полям по имени класса, то произойдёт ошибка.
print(Figure.type)
print(Figure.color)
Результат:
AttributeError: type object 'Figure' has no attribute 'type'
Методы классов могут быть: статическими, классовыми (среднее между статическими и обычными) и обычные.
Статический метод создаётся с декоратором @staticmethod;
Классовый метод создаётся с декоратором @classmethod, первым аргументом в него передаётся cls;
Обычный метод создаётся без специального декоратора, ему первым аргументом передаётся self.
Пример 13-2.(файл 13-2.py)
class MyClass:
@staticmethod
def ex_static_method():
print("static method")
@classmethod
def ex_class_method(cls):
print("class method")
def ex_method(self):
print("method")
Статический и классовый метод можно вызвать, не создавая экземпляр класса,
для вызова ex_method() нужен объект:
MyClass.ex_static_method()
MyClass.ex_class_method()
#MyClass.ex_method() # Ошибка вызова метода
m = MyClass()
m.ex_method()
2
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Результат:
static method
class method
method
3
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Отношения между классами в ООП
и отображение их в диаграммах UML
UML - (англ. Unified Modeling Language — унифицированный язык моделирования) — язык графического описания для объектного моделирования в области разработки программного обеспечения, моделирования бизнес-процессов, системного
проектирования и отображения организационных структур.
Классы являются отражениями (моделями) различных сущностей и явлений реального и виртуального миров. Между ними могут существовать различные виды взаимоотношений. Мы уже рассмотрели основной вид отношений между классами –
«наследование». Однако наследование – это далеко не единственный вид отношений
между классами.
Можно привести аналогию из реального мира. Наши родственники – это наши
классы-предки и классы-наследники. Однако мы взаимодействуем в этом мире не
только с родственниками, но и с другими людьми. С некоторыми из них мы взаимодействуем лишь однократно, с другими – периодически, с третьими – в течение длительного времени. Так и классы, могут иметь различные виды взаимоотношений друг
с другом.
Изолированные классы не имеют отношений. Чаще встречаются классы, которые имеют между собой те или иные типы отношений. Рассмотрим основные типы
отношений между классами.
Использование (Зависимость) – это самая слабая разновидность отношений между классами. Наличие зависимости означает, что один класс использует
другой класс, или располагает информацией о его существовании. Обычно данная
связь является краткосрочной : зависимый класс быстро взаимодействует с целевым
классом, но не нуждается в поддержании связи на сколько-нибудь продолжительное
время.
4
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Использование (Зависимость) между классами в диаграммах классов UML выражается пунктирной линией со стрелкой, ведущей от зависимого класса к используемому.
WindowClosingEvent
Window
Ассоциация.
Отношение Ассоциации сильнее отношения Зависимости. Обычно оно показывает, что один класс поддерживает отношение с другим классом в течение длительного периода.
Ассоциация обычно выражается формулировкой «содержит».
Ассоциация обозначается сплошной линией между классами, участвующими в
отношениях.
Cursor
Window
Агрегирование.
Агрегирование является усиленной разновидностью ассоциации. В отличие от
ассоциации, агрегирование обычно означает отношение владения, а также может подразумевать связи между жизненными циклами. Агрегирование обычно формулируется
в виде «…является владельцем…».
5
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Агрегирование
обозначается ромбовидной
стрелкой
рядом
с классом-
владельцем и сплошной линией, ведущей к подчинённому классу.
Rectangle
Window
Композиция.
Композиция представляет очень сильные отношения между классами, граничащими с
внедрением. Композиция отражает отношение «целое – часть».
Отношение композиции обычно формулируется в виде «…является частью…».
Отношение композиции обозначается заполненным ромбом рядом с классомвладельцем и сплошной линией, ведущей к подчинённому классу.
TitleBar
Window
Обобщение (расширение, наследование).
Отношение обобщения указывает на то, что подчинённый (дочерний) класс отношения является менее общей (или более специализированной) версией исходного
(родительского) класса. Исходный класс также называется суперклассом, а производный – подклассом.
Обобщение обычно читается в виде «…является частным случаем…» от специализированного класса к общему.
6
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Отношение обобщения обозначается сплошной линией с замкнутой треугольной
стрелкой, ведущей от специализированного класса к общему.
Person
Student
При проектировании отношений между классами надо учитывать некоторые
общие рекомендации. В частности, вместо наследования следует предпочитать композицию. При наследовании весь функционал класса-наследника жёстко определён на
этапе компиляции. И во время выполнения программы мы не можем его динамически
переопределить. А класс-наследник не всегда может переопределить код, который
определён в родительском классе. Композиция же позволяет динамически определять
поведение объекта во время выполнения, и поэтому является более гибкой.
Вместо композиции следует предпочитать агрегацию, как более гибкий способ
связи компонентов. В то же время не всегда агрегация уместна. Например, у нас есть
класс человека, который содержит объект нервной системы. Понятно, что в реальности, по крайней мере на текущий момент, невозможно вовне определить нервную систему и внедрить её в человека. То есть в данном случае человек будет главным компонентом, а нервная система - зависимым, подчинённым, и их создание и жизненный
цикл будет происходить совместно, поэтому здесь лучше выбрать композицию.
Видимость
Для обозначения видимости в языке UML используются следующие символы :
+
#
~
public
Общий, публичный
private
Приватный, закрытый
protected
Защищённый
package
Пакет, сборка, внутренний
7
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Программное моделирование предметной области
В настоящее время программное обеспечение разрабатывается для самых разных объектов и явлений, а также абстрактных понятий. И далеко не всегда объекты
находятся в отношении «предок-потомок». Рассмотрим примеры.
В каком отношении находятся объекты «Комната» и «Стена» ? Находятся ли
они в отношении «предок-потомок» ?
В каком отношении находятся объекты «Комната» и «Мебель» ? Находятся ли
они в отношении «предок-потомок» ?
В каком отношении находятся объекты «Собака» и «Автомобиль» ? Находятся
ли они в отношении «предок-потомок» ?
В каком отношении находятся объекты «Окно в ОС Window» и «Заголовок окна»? Находятся ли они в отношении «предок-потомок» ?
В каком отношении находятся объекты «Целая переменная» и «Класс Random»?
Находятся ли они в отношении «предок-потомок» ?
Во всех перечисленных случаях ответ будет – НЕТ
8
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Объекты могут находиться в самых различных отношениях. В процессе развития
объектно-ориентированного анализа и проектирования были выделены следующие
основные виды взаимоотношений между объектами.
Таблица 1 - Виды связей между объектами
1
Никаких отношений
2
Использование
(Зависимость)
3
Ассоциация
4
Агрегация
(агрегирование)
5
Композиция
6
Наследование
Объекты полностью независимы друг от друга (самый
распространённый вид связи в реальном мире);
Кратковременное (в т.ч. одноразовое) взаимодействие;
Очень слабый вид связи, существующий длительное
время или постоянно;
Один объект содержит в себе другой объект, который
существует независимо от него; другими словами зависимый объект принадлежит этому объекту, но может
также принадлежать другому объекту.
Отражает сильную связь между объектами; композиция
отражает отношение «целое – часть»; зависимый объект
НЕ МОЖЕТ существовать без основного объекта;
Родственный вид связи, наследование; зависимый объект является частным случаем основного объекта.
9
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Ответить на вопросы
В каком отношении находятся объекты «Комната» и «Стена» ?
В каком отношении находятся объекты «Комната» и «Мебель» ?
В каком отношении находятся объекты «Собака» и «Автомобиль» ?
В каком отношении находятся объекты «Окно в ОС Window» и «Заголовок окна»?
В каком отношении находятся объекты «Целая переменная» и «Класс Random»?
В каком отношении находятся объекты «Оружие» и «Автомат Калашникова» ?
10
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
ОТВЕТЫ на вопросы
В каком отношении находятся объекты «Комната» и «Стена» ?
Стена это неотъемлемая часть комнаты, она не может существовать без комнаты. В то же время стена, это не частный случай комнаты.
Поэтому ответ будет 5 Композиция
В каком отношении находятся объекты «Комната» и «Мебель» ?
Мебель находится в комнате, она принадлежит комнате, но в то же время её
можно вполне переставить в другую комнату. Т.е. она относительно независима от
комнаты.
Ответ 4 Агрегация
В каком отношении находятся объекты «Собака» и «Автомобиль» ?
Ни в каком.
Ответ 1 Никаких отношений
В каком отношении находятся объекты «Окно в ОС Window» и «Заголовок окна»?
Заголовок окна не может существовать вне окна.
Ответ 5. Композиция
В каком отношении находятся объекты «Целая переменная» и «Класс Random»?
Они независимы друг от друга, но мы можем создать целую переменную на основе Random
Ответ 2. Использование
В каком отношении находятся объекты «Оружие» и «Автомат Калашникова» ?
Автомат Калашникова – частный случай Оружия.
Ответ 6. Наследование
11
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Примеры взаимосвязи объектов (классов) на Python
Пример 1. Никаких отношений между классами
# 1.Никаких отношений между классами
class Person:
def __init__(self, nm, ag):
self.name = nm
self.age = ag
def PrintPerson(self):
print('Имя - ',self.name,' ,возраст - ',self.age)
def NextYear(self):
self.age +=1
def __del__(self):
print('Объект уничтожен')
class Color:
def __init__(self, col):
self.color_name = col
def __repr__(self):
return "Цвет - {0}".format(self.color_name)
P1 = Person("Иван Иванов",20) # Создали объект класса Person
P1.PrintPerson()
C1 = Color("Красный") # Создали объект класса Color
print(C1)
Результат:
Имя - Иван Иванов
Цвет - Красный
,возраст -
12
20
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Пример 2. Использование
# 2.Использование
import random
num = 0 # num - Объект встроенного класса Int
num = random.randint(0,100) # Использовали для num встроенный
класс random
print(num)
# Далее объект num живёт своей независимой от random жизнью
13
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Пример 3. Ассоциация
class Sub(object):
def __init__(self, name):
self.name = name
#
def __repr__(self):
return "'sub: {0}'".format(self.name)
#
class Main(object):
#
def __init__(self, name):
self.name = name
self.sub_list = []
#
def __repr__(self):
return "'main: {0}'".format(self.name)
#
sub1 = Sub("first")
sub2 = Sub("second")
#
main = Main("first")
main.sub_list.append(sub1)
main.sub_list.append(sub2)
#
print(sub1)
print(sub2)
print(main)
print("main-sublist: ", main.sub_list)
Здесь главный класс Main содержит постоянно список sub_list объектов
класса Sub. Объекты sub1, sub2 и main малозависимы друг от друга. Удаление одних
не приведёт к удалению других.
14
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Пример 4. Агрегация
# 4. Агрегация
class Salary(object):
def __init__(self, pay):
self.pay = pay
def getTotal(self):
return (self.pay * 12)
class Employee(object):
def __init__(self, pay, bonus):
self.pay = pay
self.bonus = bonus
def annualSalary(self):
return "Total: " + str(self.pay.getTotal() +
self.bonus)
salary = Salary(100)
employee = Employee(salary, 10) # Объект класса Salary
передаётся в качестве параметра
print(employee.annualSalary())
Результат:
Total: 1210
В этом примере объект класса Salary постоянно используется в классе Employee
и передаётся туда в качестве параметра. При этом если удалить объект employee класса Employee, то объект salary класса Salary остаётся жив-здоров.
15
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Пример 5. Композиция
# Композиция
class Salary:
def __init__(self,pay):
self.pay = pay
def getTotal(self):
return (self.pay*12)
class Employee:
def __init__(self,pay,bonus):
self.pay = pay
self.bonus = bonus
self.salary = Salary(self.pay)
def annualSalary(self):
return "Total: " + str(self.salary.getTotal() +
self.bonus)
employee = Employee(100,10)
print(employee.annualSalary())
Результат:
Total: 1210
Здесь объект класса Salary практически внедрён в класс Employee и является его
полем. В этом случае, при удалении объекта employee будет также удалён и объект
salary (они здесь являются неразрывным целым, как, например пары, «комната-стена»,
«дом-крыша», «автомобиль-двигатель»).
Связь 6. Наследование была нами рассмотрена ранее (Person-Student-Diplomnik).
16
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Понятие о паттернах проектирования
Паттерн проектирования в ООП – это
определённый шаблон построения классов.
Паттерны отражают архитектурные особенности построения классов в ООП.
ООП – это ещё и задача проектирования:
как использовать классы для моделирования
полезных объектов.
Идея паттернов как способов описания решения распространённых проблем в
области проектирования классов ООП стала популярной благодаря известной работе
четырёх авторов Эриха Гаммы, Ричарда Хелма, Ральфа Джонсона, Джона Влиссидеса,
которая называлась "Design Patterns: Elements of Reusable Object-Oriented Software" (на
русском языке известна как "Приемы объектно-ориентированного проектирования.
Паттерны проектирования") и которая вышла в свет в 1994 году. А сам коллектив авторов нередко называют "Банда четырёх" или "Gang of Four" или сокращенно GoF.
Данная книга, по сути, являлась первой масштабной попыткой описать распространённые в ООП способы проектирования программ. В настоящее время применение
паттернов считается хорошей практикой ОО-программирования.
Паттерны, как правило, не зависят от языка программирования. Их принципы
применения будут аналогичны и в C#, и в Java, и Python и в других языках.
В то же время не стоит применять паттерны ради самих паттернов. Хорошая
программа предполагает использование паттернов. Однако не всегда паттерны упрощают и улучшают программу. Неоправданное их использование может привести к
усложнению программного кода, ухудшению его качества. Паттерн должен быть
оправданным и эффективным способом решения проблемы.
Паттерны классифицируют по некоторым признакам. Рассмотрим группы паттернов.
17
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Порождающие паттерны — это паттерны, которые абстрагируют процесс инстанцирования (англ. instance – экземпляр класса) или, иными словами, процесс порождения классов и объектов. Среди них выделяются следующие:
Абстрактная фабрика (Abstract Factory);
Строитель (Builder);
Фабричный метод (Factory Method);
Прототип (Prototype);
Одиночка (Singleton).
Cтруктурные паттерны - рассматривают, как классы и объекты образуют бо-
лее крупные структуры - более сложные по характеру классы и объекты. К таким шаблонам относятся:
Адаптер (Adapter);
Мост (Bridge);
Компоновщик (Composite);
Декоратор (Decorator);
Фасад (Facade);
Приспособленец (Flyweight);
Заместитель (Proxy).
Поведенческие паттерны - определяют алгоритмы и взаимодействие между
классами и объектами (то есть их поведение). Среди подобных шаблонов можно выделить следующие:
Цепочка обязанностей (Chain of responsibility);
Команда (Command);
Интерпретатор (Interpreter);
Итератор (Iterator);
Посредник (Mediator);
Хранитель (Memento);
18
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
Наблюдатель (Observer);
Состояние (State);
Стратегия (Strategy);
Шаблонный метод (Template method);
Посетитель (Visitor).
Распространённость различных паттернов не является величиной постоянной. С
течением времени одни паттерны набирают популярность, другие её теряют, третьи
остаются на одном уровне.
Паттерны проектирования в Python
При разработке программ на Python некоторые из перечисленных выше паттернов покажутся очень похожими друг на друга, а некоторые вообще не нужны. Объясняется это тем, что изначально паттерны проектирования предназначались, прежде
всего, для C++, и приходилось преодолевать некоторые ограничения этого языка. В
Python таких ограничений нет (Python появился на 20 лет позже, чем C++ !).
Философия Python базируется на хорошо продуманных лучших практиках программирования. Многие шаблоны проектирования уже встроены в язык. Например,
это Генераторы. Разработчики используют их, даже не задумываясь. Ряд популярных
паттернов очень легко реализовать благодаря динамической природе языка. А некоторые не используются в Python, так как в них нет необходимости.
Пример паттерна Singletone на Python
# Паттерн Singleton на Python
class Singleton(object):
obj = None # единственный экземпляр класса
def __new__(cls, *args, **kwargs):
if cls.obj is None:
19
Объектно-ориентированный анализ
и программирование. Лекция 2020 – 3 .
cls.obj = object.__new__(cls, *args, **kwargs)
return cls.obj
single = Singleton() # Создали один объект класса
single.attr = 42
# Присвоили значение полю данных
newSingle = Singleton() # Создали второй объект класса
print(newSingle.attr) # 42
if newSingle is single:
# true - а они равны
print("Object is single")
Результат:
42
Object is single
Здесь __new__(cls, *args, **kwargs) – это всегда classmethod. Вызывается для создания экземпляра класса, перед вызовом __init__.
Оператор is проверяет равенство двух объектов. Два объекта равны, если равны
их ссылки (т.е. адреса ячеек в ОП).
Объект класса Singletone всегда существует в единственном числе.
20