
97-100
Объектно-ориентированное программирование (ООП) — это технология создания сложного программного обеспечения, которое основано на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы образуют иерархию с наследованием свойств.
Основное достоинство ООП — это сокращение количества межмодульных вызовов и уменьшение объёмов информации передаваемой между модулями. Это достигается за счет более полной локализации данных и интегрирования их с подпрограммами обработки.
Основные недостатки в ООП — это некоторое снижение быстродействия из-за более сложной организации программной системы, а также, как правило, заметное увеличение объёма бинарного кода (особенно при использовании стандартных библиотек классов в небольших программах) из-за того, что большинство современных компиляторов и компоновщиков не способны выявить и удалить весь код, приходящийся на неиспользуемые классы, виртуальные методы и другие элементы ООП.
В Object Pascal классы задаются с помощью типа object, аналогичного record, который кроме полей данных может содержать заголовки процедур и функций (они называютсяметодами). Имена описываемых методов следуют за именем класса через точку.
Инкапсуляция — механизм языка программирования, который ограничивает доступ к составляющим объект компонентам (методам и переменным), делает их приватными, т.е. доступными только внутри объекта. Важно понимать, что к инкапсулированной переменной можно обратиться, когда пишешь реализацию класса, но при самом его использовании доступа не будет.
Это важный инструмент ООП наряду с полиморфизмом, Наследованием и Абстракцией данных.
В то же время, в языках поддерживающих замыкания, инкапсуляция рассматривается как понятие не присущее исключительно объектно-ориентированному программированию. Также, реализации абстрактных типов данных (например, модули) предлагают схожую модель инкапсуляции.
Delphi
В Delphi для создания скрытых полей или методов их достаточно объявить в секции private.
TMyClass = class
private
FMyField: Integer;
procedure SetMyField(const Value: Integer);
function GetMyField: Integer;
public
property MyField: Integer read GetMyField write SetMyField;
end;
Для создания интерфейса доступа к скрытым полям в Delphi введены свойства.
C++
class A
{
public:
int a, b; //данные открытого интерфейса
int ReturnSomething(); //метод открытого интерфейса
private:
int Aa, Ab; //скрытые данные
void DoSomething(); //скрытый метод
};
Класс А инкапсулирует свойства Aa, Ab и метод DoSomething, представляя внешний интерфейс ReturnSomething, a, b.
Наследование — механизм языка позволяющий написать новый класс на основе уже существующего(родительского, базового) класса. Класс–потомок может добавить собственные методы и свойства и пользоваться родительскими методами и свойствами. Позволяет строить иерархии классов.
Это важный инструмент ООП наряду с Инкапсуляцией, Полиморфизмом и Абстракцией данных.
Delphi (Object Pascal)
Для использования механизма наследования в Delphi необходимо в объявлении класса справа от слова class указать класс предок:
Предок:
TAncestor = class
private
protected
public
// Виртуальная процедура
procedure VirtualProcedure; virtual; abstract;
procedure StaticProcedure;
end;
Наследник:
TDescendant = class(TAncestor)
private
protected
public
// Перекрытие виртуальной процедуры
procedure VirtualProcedure; override;
procedure StaticProcedure;
end;
Абсолютно все классы в Delphi являются потомками класса TObject. Если класс-предок не указан, то подразумевается, что новый класс является прямым потомком класса TObject.
Множественное наследование в Delphi частично поддерживается за счёт использования классов-помощников (Сlass Helpers).
Какие существуют модификаторы уровня доступа?
Public — открытый. Все методы и свойства , объявленные после этого модификатора доступны из любой части программы. Private — закрытый. Методы и свойства, уровня доступа private разрешено использовать только внутри класса, запрещено использование в производных классах. Protected — защищенный. Эквивалентен модификатору private с единственным исключением: разрешено использование методов и свойств в производных классах.
Полиморфизм(от греч. πολὺ- — много, и μορφή — форма) — возможность класса–потомка менять реализацию класса–отца сохраняя при этом его интерфейс.
Это важный инструмент ООП наряду с Инкапсуляцией, Наследованием и Абстракцией данных.
Кратко смысл полиморфизма можно выразить фразой: «Один интерфейс, множество реализаций».
Полиморфизм позволяет писать более абстрактный код тем самым повышая коэффициент повторного использования кода. Общие свойства объектов объединяются в систему, которую могут называть по-разному — интерфейс или класс.
В программировании полиморфизм используется для того, чтобы сделать приложения более модульными и расширяемыми. Вместо беспорядочных условных предложений, описывающих различные направления действия, вы создаете взаимозаменяемые объекты, которые подбираете согласно своим нуждам. Это основная задача полиморфизма
Приведу наглядный пример. Все садовые деревья плодоносят, независимо от сорта дерева. Отсюда вытекает, что единым интерфейсом является объект «дерево» с методом «созревание плодов». А вот как, и каким способом созревает плод, является индивидуальной реализацией каждого сорта отдельно. Перенесем выше сказанное на программный язык.
Создадим класс GardenTree, в котором реализуем только один метод «maturation»:
package my.polimorfism;
public class GardenTree {
public void maturation() {
System.out.println("Parent class: maturation.");
}
}
Далее создадим два класса наследующих класс GardenTree, и переопределяющих методmaturation родительского класса:
package my.polimorfism;
public class Apple extends GardenTree {
public void maturation() {
System.out.println("Maturation apple.");
}
}
package my.polimorfism;
public class Cherry extends GardenTree {
public void maturation() {
System.out.println("Maturation cherry.");
}
}
Ну и собственно создаем класс, в котором реализуется идеология полиморфизма:
package my.polimorfism;
public class App
{
public static void ripening_fruit(GardenTree i) {
i.maturation();
}
public static void main( String[] args ) {
GardenTree apple = new Apple();
GardenTree cherry = new Cherry();
ripening_fruit(apple);
ripening_fruit(cherry);
}
}
Вызов метода maturation классов Apple и Cherry, через единый метод и является полиморфизмом.
Мы можем без проблем добавить класс Pear, в котором будет своя реализация метода maturation.
package my.polimorfism;
public class Pear extends GardenTree {
public void maturation() {
System.out.println("Maturation pear.");
}
}
И вызвать его метод maturation, через единый интерфейс ripening_fruit.
GardenTree pear = new Pear();
ripening_fruit(pear);
При полиморфизме мы не плодим метод ripening_fruit для каждого сорта дерева, а передаем в аргумент данного метода базовый класс, вместо дочернего класса.
Если внимательно присмотреться к нашему коду, то можно увидеть, что мы используем восходящее преобразование.
GardenTree apple = new Apple();
GardenTree cherry = new Cherry();
GardenTree pear = new Pear();
Конструкторы и деструкторы отвечают за существование объекта в памяти, т.е. выделяют память для экземпляра класса, затем и освобождают ее.
Конструктор – это специальный вид подпрограммы, присоединенный к классу. Его на-значение – создавать представителей (экземпляры) класса. Он ведет себя как функция, которая возвращает ссылку на вновь созданный экземпляр класса, т.е. на объект. Одновременно выделяется память для хранения значений полей экземпляра класса.
Деструктор – это специальная разновидность подпрограммы, присоединенной к классу. Его назначение заключается в уничтожении экземпляра класса, т.е. объекта и освобождении памяти, выделенной под экземпляр.
Синтаксис объявления конструкторов и деструкторов:
Type <имя класса>=Сlass[{Имя родительского класса>)] . . . Constructor Имя конструктора>[(<параметры>)]; [Override;] Destructor <имя деструктора>[(<параметры>)}; [Override;] End;
Примечания: • Объявляются конструкторы и деструкторы, как правило, в разделе Public класса. • В классе может быть объявлено несколько конструкторов, однако чаще бывает один конструктор. Общепринятое имя для единственного конструктора Create. • В одном классе может быть объявлено несколько деструкторов, но чаще бывает один деструктор без параметров (всегда!) с именем Destroy. • За объявлением деструктора по имени Destroy следует указывать ключевое слово-директиву Override, разрешающее выполнение предусмотренных по умолчанию действий для уничтожения экземпляра объекта, если при его создании возникла какая-либо ошибка. Фактически Override переопределяет метод предка • Метод Free так же удаляет (разрушает) экземпляры класса, предварительно проверяя их на Nil.