Slide 1

Slide 1 text

ОБЪЕКТНО- ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ Лекция № 1 / 10
 09.04.2018 г.

Slide 2

Slide 2 text

ОТНОШЕНИЯ
 МЕЖДУ КЛАССАМИ • Наследование • Композиция • Агрегация • Ассоциация Вспоминаем!

Slide 3

Slide 3 text

class Boss { Slave slave; std::unique_ptr slave2; public: Boss() : slave(), slave2(new AnotherSlave) {} }; Композиция

Slide 4

Slide 4 text

class Order { // ... }; class User { std::vector orders; public: // ... }; Агрегация

Slide 5

Slide 5 text

Ассоциация class Auditor { public: // ... bool auditRead(const string &key); bool auditWrite(const string &key); }; class AuditedKVStore { AuditedKVStore(Auditor &_auditor, map *_storage) : auditor(_auditor), storage(_storage) {} string get(const string &key); // ... private: Auditor &auditor; map *storage; };

Slide 6

Slide 6 text

ГРАФИЧЕСКАЯ НОТАЦИЯ SquareEquation —————————— a, b, c: double —————————— + numberOfRoots(): int + root1(): double + root2(): double – discriminant(): double # protectedMethod(): int

Slide 7

Slide 7 text

SquareEquation —————————— /+ numberOfRoots(): int … Equation —————————— + numberOfRoots(): int Наследование

Slide 8

Slide 8 text

Композиция Car —————————— wheels[4]: Wheel —————————— + getHorsePower(): int
 + getMake(): string
 … Wheel ——————————
 diameter: int …

Slide 9

Slide 9 text

Агрегация Professor ——————————— name: string dob: date courses: vector Course ——————————
 name: string …

Slide 10

Slide 10 text

Ассоциация Reader ——————————— + getLine(): string Processor ——————————
 reader: Reader & …

Slide 11

Slide 11 text

Все диаграммы UML

Slide 12

Slide 12 text

From: Начальник 
 To: Кодер Вася 
 Date: Mon, 10 Nov 2014 07:59:11 +0600
 Subject: СРОЧНО!!!!!!!!!!!!!1 Вася, нужно написать программу, форматирующую текстовые файлы по заданной ширине и с заданным выравниванием: по левому, правому краю и по центру. Абзацы разделены пустой строкой. Как только что-то будет, присылай. —
 Начальник ACME

Slide 13

Slide 13 text

TextFormatter ——————————————— width: int algorithm: enum { Left, Right, Center } ——————————————— + TextFormatter(width : int,
 algorithm: enum) + format(in_fn, out_fn: string) God Object

Slide 14

Slide 14 text

• Открытие файла на чтение. • Открытие файла на запись. • Построчное чтение файла. • Форматирование (в зависимости от параметров). • Построчная запись в файл. Список обязанностей TextFormatter

Slide 15

Slide 15 text

TextFormatter ——————————————— width: int algorithm: enum { Left, Right, Center } in: istream & out: ostream & ——————————————— + TextFormatter(width : int,
 algorithm: enum) + format(in: istream &, out: ostream &) istream ifstream istringstream ostream ofstream ostringstream Используем абстракции ввода/вывода: istream и ostream

Slide 16

Slide 16 text

1. Считываем строку. Разбиваем на слова. 2. Если строка непустая, то добавляем слова в массив готовых слов. 3. Если строка пустая или конец файла, то в цикле: 1. Из массива готовых слов выбираем первые N слов так, чтобы они по ширине помещались в строку с учётом пробелов, а N было максимальным:
 (суммарная длина слов + количество слов – 1) <= ширина. 2. Форматируем выбранные N слов нужным способом, выводим, удаляем из массива. 3. Цикл повторяется до тех пор, пока массив готовых слов не опустеет. 4. Вывод пустой строки и переход к п. 1, если ещё не конец файла. Примерный алгоритм форматирования текста

Slide 17

Slide 17 text

ParagraphFormatter ——————————————— width: int words: vector ——————————————— + addLine(line: string) + getFormattedLine(): string # formatLine(): string LeftJustifyFormatter ————————— /# formatLine(): string RightJustifyFormatter ————————— /# formatLine(): string CenteringFormatter ————————— /# formatLine(): string

Slide 18

Slide 18 text

TextFormatter —————————————————— pf: ParagraphFormatter in: istream & out: ostream & —————————————————— + TextFormatter(pf: ParagraphFormatter, in: istream &, out: ostream &) + format() istream ostream ParagraphFormatter LeftJustifyFormatter RightJustifyFormatter CenteringFormatter

Slide 19

Slide 19 text

using namespace std; static void drainFormatter(ParagraphFormatter *pf, ostream &os) { for (;;) { string line = pf->getFormattedLine(); if (line.empty()) break; os << line << endl; } } void TextFormatter::format() { string line; while (getline(in, line)) { if (line.empty()) { drainFormatter(pf, out); out << endl; } else pf->addLine(line); } drainFormatter(pf, out); } Примерный код TextFormatter::format()

Slide 20

Slide 20 text

ПРИНЦИП ПОДСТАНОВКИ ЛИСКОУ • Liskov Substitution Principle (LSP). • «Подтипы должны быть заменяемы их исходными типами».

Slide 21

Slide 21 text

• «Пусть q(x) является свойством, верным относительно объектов x некоторого типа T. Тогда q(y) также должно быть верным для объектов y типа S, где S является подтипом T». • «Функции, которые используют базовый тип, должны иметь возможность использовать подтипы базового типа, не зная об этом». • «Подкласс не должен требовать от вызывающего кода больше, чем базовый класс, и не должен предоставлять вызывающему коду меньше, чем базовый класс».

Slide 22

Slide 22 text

SQUARE И RECTANGLE • Если класс Rectangle имеет интерфейс, предполагающий раздельность изменений ширины и высоты (setWidth, setHeight), то Square нельзя наследовать от Rectangle. • Можно сделать, чтобы у класса Square и setWidth, и setHeight устанавливали как высоту, так и ширину, поддерживая «квадратность», но…

Slide 23

Slide 23 text

Сломается, если передать Square void testArea(Rectangle &r) { r.setWidth(5); r.setHeight(4); assert(r.area() == 20); }

Slide 24

Slide 24 text

ЛИНИЯ И ОТРЕЗОК Стоит ли наследовать класс LineSegment от класса Line? (если Line моделирует бесконечную линию)

Slide 25

Slide 25 text

ПРИНЦИП ИНВЕРСИИ ЗАВИСИМОСТЕЙ • Dependency Inversion Principle (DIP). • Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба типа модулей должны зависеть от абстракций. • Абстракции не должны зависеть от подробностей, наоборот, подробности должны зависеть от абстракций.

Slide 26

Slide 26 text

Функция высокого уровня Функции низкого уровня void copy() { int ch; while ((ch = getchar()) != EOF) putchar(ch); }

Slide 27

Slide 27 text

«СЛОИСТАЯ СТРУКТУРА» Слой Policy Слой Mechanism Слой
 Utility Выбор 
 нужного 
 алгоритма Реализация
 алгоритмов Вспомогательные
 низкоуровневые
 функции Policy слишком сильно зависит от Utility :(

Slide 28

Slide 28 text

Слой Policy Policy Service Interface Слой Mechanism Mechanism Service Interface Слой Utility Инверсия зависимостей

Slide 29

Slide 29 text

Сильная зависимость.
 Невозможно использовать Button
 для управления чем-то еще Button Lamp class Lamp { public: void on(); void off(); }; class ToggleButton { Lamp lamp; bool is_on; public: ToggleButton() : is_on(false) {} void toggle() { is_on = !is_on; if (is_on) lamp.on(); else lamp.off(); } };

Slide 30

Slide 30 text

ToggleButton Lamp Switchable class Switchable { public: virtual void on() {} virtual void off() {} }; class Lamp: public Switchable { /* ... */ }; class ToggleButton { Switchable *object; bool is_on; public: ToggleButton(Switchable *o) : object(o), is_on(false) {} void toggle() { is_on = !is_on; if (is_on) object->on(); else object->off(); } };

Slide 31

Slide 31 text

#define THERMOMETER 0x86 #define FURNACE 0x87 #define ENGAGE 1 #define DISENGAGE 0 void regulate(double minTemp, double maxTemp) { for (;;) { while (in(THERMOMETER) > minTemp) wait(1); out(FURNACE, ENGAGE); while (in(THERMOMETER) < maxTemp) wait(1); out(FURNACE, DISENGAGE); } } «Поддержание температуры»

Slide 32

Slide 32 text

void regulate(Thermometer &t, Heater &h, double minTemp, double maxTemp) { for (;;) { while (t.read() > minTemp) wait(1); h.engage(); while (t.read() < maxTemp) wait(1); h.disengage(); } } Применение принципа инверсии зависимостей

Slide 33

Slide 33 text

Управление через порт 0x87 Heater Функция regulate() Канал ввода c порта 0x86 Thermometer read() engage()
 disengage()

Slide 34

Slide 34 text

КОНЕЦ ДЕСЯТОЙ ЛЕКЦИИ