Объектноориентированное программирование 7.1 Что такое ООП? 7.2 Объекты и классы 7.3 Скрытие внутреннего устройства объектов 7.4 Иерархия классов К. Поляков, 2011 http://kpolyakov.narod.ru 1 2 Объектноориентированное программирование 7.1 Что такое ООП? К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 3 Направления развития ПО • переход от расчетов по формулам к сложным задачам моделирования систем • увеличение объемов обрабатываемых данных • повышение сложности программ, увеличение их длины (до миллионов строк!) ! Сложность программ превышает возможности одного человека. В итоге: • коллективная разработка • каждый делает свою часть независимо от других • части программы легко «собрать» вместе ? К. Поляков, 2011 Как? http://kpolyakov.narod.ru Объектно-ориентированное программирование 4 Борьба со сложностью «Техника борьбы со сложностью известна с античных времен: “Divide et impera” (разделяй и властвуй)». Э. Дейкстра Алгоритмическая декомпозиция задача > 100 000 строк??? подзадача 1 подзадача 2 подзадача 3 подзадача 2.1 подзадача 2.2 подзадача 2.3 Декомпозиция – это разбиение системы на подсистемы, каждая из которых может изучаться отдельно. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 5 Объектный подход Люди воспринимают мир, состоящий из объектов (Р. Декарт). К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 6 Абстракция Абстракция – это выделение существенных характеристик объекта, отличающих его от других объектов. Иллюстрация из книги Г. Буч, Объектно-ориентированный анализ и проектирование с примерами приложений на С++. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 7 Абстракция в программировании • программа – это множество взаимодействующих объектов (моделей) • объекты имеют свойства и поведение • объекты не «знают» внутреннее устройство других объектов А Б1 Б Б2 В1 В2 В3 Б3 Г Г2 Г1 К. Поляков, 2011 В Объектная декомпозиция http://kpolyakov.narod.ru Объектно-ориентированное программирование 8 Абстракция в программировании Верхний уровень: • определить, ЧТО делает каждый объект • определить ИНТЕРФЕЙС – способ обмена данными между объектами Б интерфейс В Нижний уровень: • определить, КАК работают объекты Б1 Б Б2 Б3 К. Поляков, 2011 интерфейс интерфейс В1 В В2 В3 http://kpolyakov.narod.ru Объектно-ориентированное программирование 9 Что такое ООП? Программирование, основанное на моделировании задачи реального мира как множества взаимодействующих объектов, принято называть объектно-ориентированным программированием (ООП). уточнение следует… К. Поляков, 2011 http://kpolyakov.narod.ru 10 Объектноориентированное программирование 7.2 Объекты и классы К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 11 Объектно-ориентированный анализ (ООА) Задачи: • выделить взаимодействующие объекты • определить их существенные свойства ? Какие свойства существенные? • описать команды, которые объекты могут выполнить (поведение) К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 12 Что такое объект? Объектом можно назвать то, что имеет четкие границы и обладает состоянием и поведением. ! Состояние объекта определяет его поведение! Примеры: «Подпрыгни!» К. Поляков, 2011 «Пли!» http://kpolyakov.narod.ru Объектно-ориентированное программирование 13 Объектная модель: пример Объекты: • дорога • машины ? • светофоры • … Описывать каждую машину отдельно? Класс – это множество объектов, имеющих общую структуру и общее поведение. Классы объектов: Дорога, Машина К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 14 Объектная модель: класс Дорога ширина длина название класса свойства Дорога длина ширина поведение (команды, методы) К. Поляков, 2011 ? Какое «поведение» могло бы быть у дороги? http://kpolyakov.narod.ru Объектно-ориентированное программирование 15 Объектная модель: класс Машина Y V X метод Машина X (координата) Y (полоса) V (скорость) двигаться узнать длину Дорога длина ширина Метод – это процедура или функция, принадлежащая классу объектов. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 16 Класс Дорога в программе Объявление (описание) класса: от type type TRoad = class Length: real; Width: integer; end; поля Поле – это переменная, принадлежащая объекту. ! Объект в памяти не создается! Аналогия: чертёж детали. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 17 Класс Дорога в программе Переменная для работы с объектом: var road: TRoad; ! road 12345 ? Объект в памяти не создается! Ссылка – это переменная, в которую можно записать адрес объекта заданного типа. адрес 12345 road := TRoad.Create; Length 0 Width 0 Конструктор – это метод класса, который вызывается для создания объектов этого класса. ! Конструктор не нужно объявлять! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 18 Создание объекта type TRoad = class Length: real; Width: integer; end; var road: TRoad; begin road := TRoad.Create; road.Length := 60; road.Width := 3; end. К. Поляков, 2011 описание класса переменная-ссылка вызов конструктора значения полей http://kpolyakov.narod.ru Объектно-ориентированное программирование 19 Новый конструктор Цель – определить начальные значения при создании объекта. длина ширина road := TRoad.Create (60, 3); Описание класса: type TRoad = class Length: real; Width: integer; constructor Create(length0: real; width0: integer); end; К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 20 Новый конструктор Реализация (программа) конструктора: метод класса TRoad constructor TRoad. Create(length0: real; width0: integer); begin if length0 > 0 then Length := length0; := length0 WidthLength := width0; else Length := 1; if width0 > 0 then Width := width0 else Width := 1; end; ? ! Что плохо? Можно обрабатывать ошибки! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 21 Класс Машина в программе Машина X (координата) Y (полоса) V (скорость) двигаться узнать длину Дорога длина ширина type TCar = class X, V: real; { координата, скорость } Y: integer; { номер полосы } road: TRoad; { ссылка на дорогу } procedure move; { двигаться вперед } end; адрес объекта класса Дорога Как машина сможет узнать длину дороги? ? К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 22 Класс Машина в программе Равномерное движение: X X 0 V t V – перемещение за 1 интервал. procedure TCar.move; begin X := X + V; { при Δt = 1 } if X > road.Length then X := 0; { «перескочить» в начало } end; длина дороги, по которой едет машина К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 23 Класс Машина в программе Добавление конструктора: адрес дороги type TCar = class ... constructor Create(road: TRoad; y0: integer; v0: real); end; полоса ? К. Поляков, 2011 скорость Чему будет равна координата X? http://kpolyakov.narod.ru Объектно-ориентированное программирование 24 Основная программа моделирования const N = 3; var road: TRoad; cars: array [1..N] of TCar; i: integer; begin road := TRoad.Create(60, N); for i:=1 to N do cars[i] := TCar.Create(road, i, 2.0*i); repeat for i:=1 to N do cars[i].move; { вывод расположения машин } until keypressed; end. ? К. Поляков, 2011 Важен ли порядок создания объектов? http://kpolyakov.narod.ru Объектно-ориентированное программирование 25 Плюсы и минусы ООП основная программа простая и понятная каждый класс может разрабатывать отдельный программист независимо можно использовать готовые классы в других программах увеличение длины полной программы (с учетом описания классов) замедление работы К. Поляков, 2011 http://kpolyakov.narod.ru 26 Объектноориентированное программирование 7.3 Скрытие внутреннего устройства объектов К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 27 Зачем скрывать внутреннее устройство? борьба со сложностью безопасность внутренних данных возможность изменять «внутренности», не меняя интерфейс Иллюстрация из книги Г. Буч, Объектно-ориентированный анализ и проектирование с примерами приложений на С++. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 28 Инкапсуляция Инкапсуляция («помещение в капсулу») – это скрытие внутреннего устройства объектов от других объектов. Класс Перо (цвет и стиль линий): type TPen = class color: string; end; ! var pen: TPen; ... pen := TPen.Create; pen.color := '#%'; writeln(pen.color); К. Поляков, 2011 'FF00FF' По умолчанию все поля общедоступные! доступно всем! http://kpolyakov.narod.ru Объектно-ориентированное программирование 29 Инкапсуляция Скрытие полей: type TPen = class private частный, FFColor: string; закрытый end; от Field – «поле» Проблема – нет доступа к полю! ! pen.color := 'FFFF00'; writeln(pen.color); ! Для доступа к закрытому полю нужны методы чтения и записи! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 30 Методы доступа к полю type TPen = class общедоступный private метод чтения FColor: string; public function getColor: string; procedure setColor(newColor: string); end; метод записи Метод чтения: • функция без параметров • возвращает значение того же типа, что и поле Метод записи: • процедура • принммает значение того же типа, что и поле К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 31 Методы доступа к полю function TPen.getColor: string; begin Result := FСolor; end; procedure TPen.setColor(newColor: integer); begin FColor := newColor; end; поле методы getColor другой объект FColor setColor TPen К. Поляков, 2011 ? Стало ли лучше? http://kpolyakov.narod.ru Объектно-ориентированное программирование 32 Проверка при изменении поля В случае ошибочного значения установить черный цвет: procedure TPen.setColor(newColor: integer); begin if Length(newColor) { ошибочное значение <> 6} then FColor := '000000' { чёрный цвет } else FColor := newColor; end; Использование: pen.setColor('FF00'); { ошибка: черный } pen.setColor('FFFF00'); { запись } writeln(pen.getColor); { чтение } ? К. Поляков, 2011 Какие ошибки не обработаны? http://kpolyakov.narod.ru Объектно-ориентированное программирование 33 Свойство pen.сolor := 'FFFF00'; { запись } writeln(pen.color); { чтение } Свойство – это способ доступа к внутреннему состоянию объекта, имитирующий обращение к его внутренней переменной. поле методы свойство getColor FColor TPen К. Поляков, 2011 color setColor другой объект http://kpolyakov.narod.ru Объектно-ориентированное программирование 34 Свойство type TPen = class private FColor: string; function getColor getColor: string ; procedure setColor setColor(newColor: string ); public property сolor: string read getColor write setColor setColor; end; свойство тип свойства метод чтения метод записи pen.сolor := 'FFFF00'; { запись } writeln(pen.color); { чтение } К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 35 Изменяем способ хранения данных FColor: string; 'FF00FF' '001234' '0000A5' методы поле FColor: integer; FF00FF16 = 16711935 123416 = 4460 A516 = 165 свойство getColor FColor color setColor TPen реализация ! другой объект интерфейс Можно менять реализацию, не меняя интерфейс! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 36 Изменяем способ хранения данных function TPen.getColor: string; begin Result := IntToHex (FColor,6); end; 6 знаков: '0000FF' X10 X16 (строка) procedure TPen.setColor(newColor: string); begin if Length(newColor) <> 6 then FColor := 0 { чёрный цвет } else FColor := StrToInt ('$' + newColor); end; строка число К. Поляков, 2011 шестнадцатеричное http://kpolyakov.narod.ru Объектно-ориентированное программирование 37 Свойства «только для чтения» Машина … V (скорость) двигаться ? Могут ли другие объекты менять скорость автомобиля? type TCar = class private Fv: real; свойство «только для чтения» ... public property v: real read Fv; ... end; К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 38 Скрытие внутреннего устройства: итог свойства методы ! К. Поляков, 2011 защита данных объекта изменение внутреннего устройства не требует изменения других объектов, если сохранить интерфейс длина программы замедление работы Выгодно для больших программ, где требуется надежность! http://kpolyakov.narod.ru 39 Объектноориентированное программирование 7.4 Иерархия классов К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 40 Классификации базовый класс ? Фрукт сочный съедобный плод дерева или кустарника Как выглядит фрукт? классы-наследники Яблоко – это разновидность фруктов. Яблоко наследует все свойства фруктов. Фото: www.statesymbolsusa.org, xenianova.files.wordpress.com, spoon.com.ua, gerbl.ru К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 41 Примеры наследования свойств базовый класс Человек Работник школы Администратор Директор К. Поляков, 2011 Завуч Ученик Учитель Уборщик Родитель Технический работник Слесарь Электрик http://kpolyakov.narod.ru Объектно-ориентированное программирование 42 Что такое наследник? Класс Б является наследником класса А, если можно сказать, что Б – это разновидность А. водоем осёл ! цветок животное ромашка автомобиль двигатель Двигатель – это часть автомобиля, а не разновидность! автомобиль косточка К. Поляков, 2011 озеро грузовик ягода http://kpolyakov.narod.ru Объектно-ориентированное программирование 43 Иерархия логических элементов Логический элемент с одним входом НЕ К. Поляков, 2011 с двумя входами И ИЛИ http://kpolyakov.narod.ru Объектно-ориентированное программирование 44 Определение ООП Объектно-ориентированное программирование – это такой подход к программированию, при котором 1) программа представляет собой множество взаимодействующих объектов, 2) … каждый из которых является экземпляром определенного класса, и … 3) классы образуют иерархию наследования. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 45 Класс «Логический элемент» ЛогЭлемент In1 (вход 1) In2 (вход 2) Res (результат) сalc (вычислить) type TLogElement = class In1, In2: boolean; Res: boolean; procedure calc; end; Сравните (плюсы, минусы): вычислить результат при изменении входов type TLogElement = class In1, In2: boolean; function res: boolean; end; вычислить результат по известным входам К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 46 Скрываем данные (инкапсуляция) type TLogElement = class private FIn1, FIn2: boolean; FRes: boolean; procedure calc; procedure setIn1(newIn1: boolean); procedure setIn2(newIn2: boolean); public property In1: boolean read FIn1 write setIn1; property In2: boolean read FIn2 write setIn2; property Res: boolean read FRes; читать прямо из поля end; свойство «только для чтения» К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 47 Процедура изменения входа procedure TLogElement.setIn1(newIn1: boolean); begin FIn1 := newIn1; calc; end; ! Сразу после изменения входа нужно пересчитать значение выхода! Проблемы: как написать метод calc? для элемента «НЕ» доступ ко второму входу не нужен! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 48 Метод calc • невозможно написать для базового класса Абстрактный метод – это метод, который объявляется, но не реализуется в классе. • разный у всех логических элементов • наследники должны его переопределять! Виртуальный метод – это метод, который могут переопределять классы-наследники. • недоступен для других объектов ! К. Поляков, 2011 Calc – это виртуальный (virtual) и абстрактный (abstract) метод! http://kpolyakov.narod.ru Объектно-ориентированное программирование 49 Метод calc type TLogElement = class private защищенный виртуальный абстрактный ... protected procedure calc; virtual; abstract; public ... end; ! protected – доступно только наследникам! Абстрактный класс – это класс, содержащий абстрактный метод («фрукт»). К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 50 Как «скрыть» свойство In2? type TLogElement = class private ... protected property In2: boolean read FIn2 write setIn2; procedure calc; virtual; abstract; public ... end; ! Наследники могут «открыть» защищенное свойство (перевести в public)! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 51 Классы-наследники: TNot наследник от … type переопределить TNot = class(TLogElement) procedure calc; override; end; procedure TNot.calc; begin FRes := not FIn1; end; ! TNot – не абстрактный класс! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 52 Классы-наследники: TLog2In наследник от … TLog2In = class(TLogElement) public свойство становится property In2; общедоступным end; ? К. Поляков, 2011 TLog2In – абстрактный класс? http://kpolyakov.narod.ru Объектно-ориентированное программирование 53 Классы-наследники: TAnd наследник от … type переопределить TAnd = class(TLog2In) procedure calc; override; end; procedure TAnd.calc; begin FRes := FIn1 and FIn2; end; ? К. Поляков, 2011 TAnd – абстрактный класс? http://kpolyakov.narod.ru Объектно-ориентированное программирование 54 Вернемся к setIn1… procedure TLogElement.setIn1 (newIn1: boolean); begin FIn1 := newIn1; calc; какой метод end; вызывается? • вызвать процедуру = перейти по заданному адресу памяти • в классе TLogElement метод calc не реализован (нет кода, нет адреса) • каждый наследник имеет свой метод calc К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 55 Обычный вызов процедуры Паскаль Ассемблер процедура ... calc; ... ... call AB12 ... AB12 ... AB14 ... AB16 ... ... Статическое связывание: адрес процедуры известен и сразу записывается в машинный код! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 56 Динамическое связывание (при выполнении) методы классов Паскаль ... calc; ... виртуальный метод ? TNot.calc Каков класс объекта? TAnd.calc TOr.calc Виртуальный метод – это метод базового класса, который могут переопределить классынаследники так, что конкретный адрес вызываемого метода определяется только при выполнении программы. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование Основная программа («И-НЕ») 57 | A | B | not(A&B) -----------------| 0 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 0 var elNot: TNot; { ссылки } elAnd: TAnd; A, B: boolean; begin elNot := TNot.Create; { создание объектов } elAnd := TAnd.Create; writeln('| A | B | not(A&B) '); writeln('-------------------'); for A:=False to True do begin { перебор вариантов } elAnd.In1 := A; for B:=false to True do begin elAnd.In2 := B; elNot.In1 := elAnd.res; { связь элементов } writeln('| ', integer(A), ' | ', integer(B), ' | ', integer(elNot.res)); end; integer(False) = 0 end; end. integer(True) = 1 ! К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 58 Классы – в модуль! unit log_elem; режим работы с объектами {$mode objfpc} interface { доступно другим модулям } type TLogElement = class ... end; ... { объявление всех классов } implementation { скрыто от других модулей } procedure TLogElement.setIn1(newIn1: boolean); begin FIn1 := newIn1; calc; end; ... end. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 59 Основная программа program logic; {$mode objfpc} uses log_elem ; var elNot: TNot; elAnd: TAnd; ... begin elNot := TNot.Create; elAnd := TAnd.Create; ... end. unit log_elem ; {$mode objfpc} interface { доступно другим модулям } ... implementation { скрыто от других модулей } ... end. К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 60 Обмен данными между объектами «И» «НЕ» & 1 ? Как может один объект передать данные другому? 2 • объект 1 должен «знать» адрес объекта 2 • у объекта 2 должен быть метод, доступный объекту 2, с помощью которого он может передать данные К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 61 Обмен данными между объектами TLogElement = class private FNextEl: TLogElement; { адрес объект 2 } FNextIn: integer; { номер входа объекта 2 } ... public procedure Link(nextElement: TLogElement; nextIn: integer); ... end; метод для установки связи выхода с входом другого элемента К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 62 Обмен данными между объектами procedure TLogElement.Link (nextElement: TLogElement; nextIn: integer); begin запомнить адрес и FNextEl := nextElement; номер входа FNextIn := nextIn; следующего элемента end; ? Когда нужно передать данные «следующему»? К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 63 Обмен данными между объектами procedure TLogElement.setIn1(newIn1: boolean); begin FIn1 := newIn1; если связь calc; установлена… if FNextEl <> nil then case FNextIn of 1: FNextEl.In1 := res; передать новые 2: FNextEl.In2 := res; данные end; end; аналогично для setIn2… ? Почему не включить передачу в метод calc? К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 64 Обмен данными между объектами elNot := TNot.Create; установить elAnd := TAnd.Create; связь elAnd.Link(elNot, 1); ... for A:=False to True do begin elAnd.In1 := A; for B:=False to True do begin elAnd.In2 := B; ... end; объект elAnd САМ сообщает объекту end; elNot, что его выход изменился К. Поляков, 2011 http://kpolyakov.narod.ru Объектно-ориентированное программирование 65 Конец фильма ПОЛЯКОВ Константин Юрьевич д.т.н., учитель информатики высшей категории, ГОУ СОШ № 163, г. Санкт-Петербург kpolyakov@mail.ru К. Поляков, 2011 http://kpolyakov.narod.ru