Объектно-ориентированное программирование основывается на представлении программы в виде множества объектов. Каждый объект относится к какому-либо классу, который, в свою очередь, занимает свое место в наследуемой иерархии. Использование ООП минимизирует избыточные данные, это улучшает управляемость, понимание программы.
Что такое ООП
Возникло как результат развития процедурного программирования. Основой объектно-ориентированных языков являются такие принципы, как:
- инкапсуляция;
- наследование;
- полиморфизм.
Некоторые принципы, которые были изначально заложены в первые ООЯ, подверглись существенному изменению.
Примеры объектно-ориентированных языков:
- Pascal. С выходом Delphi 7 на официальном уровне стал называться Delphi. Основная область использования Object Pascal - написание прикладного ПО.
- C++ широко используется для разработки программного обеспечения, является одним из самых популярных языков. Применяется для создания ОС, прикладных программ, драйверов устройств, приложений, серверов, игр.
- Java - транслируется в байт-код, обрабатывается виртуальной машиной Java. Преимуществом такого способа выполнения является независимость от операционной системой и оборудования. Существующие семейства: Standard Edition, Enterprise Edition, Micro Edition, Card.
- JavaScript применяется в качестве языка сценариев для web-страниц. Синтаксис во многом напоминает Си и Java. Является реализацией Ecmascript. Сам Ecmascript используется в качестве основы для построения других скриптовых языков, таких как JScript, ActionScript.
- Objective-C построен на основе языка Си, а сам код Си понятен компилятору Objective-C.
- Perl - высокоуровневый интерпретируемый динамический язык общего назначения. Имеет богатые возможности для работы с текстом, изначально разработан именно для манипуляций с текстом. Сейчас используется в системном администрировании, разработке, сетевом программировании, биоинформатике и т. д.
- PHP. Аббревиатура переводится как препроцессор гипертекста. Применяется для разработки веб-приложений, в частности серверной части. С его помощью можно создавать gui-приложения с помощью пакетов PHP-GTK, PHP-Qt, WinBinder.
- Python - язык общего назначения, ориентирован на повышение производительности разработчика и читаемость кода. Был разработан проект Cython, с помощью которого осуществляется трансляция программ, написанных на Python в код на языке Си.
Абстракция
Любая книга из рода “Объектно-ориентированное программирование для чайников” выделяет один из главных принципов - абстракцию. Идея состоит в разделении деталей или характеристик реализации программы на важные и неважные. Необходима для крупных проектов, позволяет работать на разных уровнях представления системы, не уточняя детали.
Абстрактный тип данных представляется как интерфейс или структура. Позволяет не задумываться над уровнем детализации реализации. АТД не зависит от других участков кода.
Известный афоризм Дэвида Уилера гласит: Все проблемы в информатике можно решить на другом уровне абстракции.
Наследование
Объектно-ориентированные языки являются наследуемыми - это один из важнейших принципов.
Обозначает, что функциональность некоторого типа может быть повторно использована. Класс, который наследует свойства другого, называется производным, потомком или подклассом. Тот, от которого происходит наследование, называется предком, базовым или суперклассом. Связь потомок-наследник порождает особую иерархию.
Существует несколько типов наследования:
- простое;
- множественное.
При множественном наследовании может быть несколько детей от одного предка, когда при простом - только один. Это является основным различием между типами.
Наследование выглядит так:
class Animal {
function draw() {
return "just animal";
}
function eat() {
return "the animal is eating";
}
}
class Cow extends Animal {
function draw() {
Return "something that looks like a cow";
}
}
Видим, что class Cow унаследовал все методы от class Animal. Теперь, если выполнить Cow.eat(), получаем "the animal is eating", соответственно, метод draw() изменен. Cow.draw() вернет “something that looks like a cow”, а Animal.draw() вернет “just animal”.
Инкапсуляция
Инкапсуляция ограничивает доступ компонентов к другим, связывает данные с методами для обработки. Для инкапсуляции используется спецификатор доступа private.
Обычно понятия инкапсуляция и сокрытие отождествляются, но некоторые языки различают эти понятия. Другими словами, критичные для работы свойства защищаются, а их изменение становится невозможным.
class Animal {
private $name;
function __construct($name) {
$this->name = $name;
}
function getName() {
return $this->name;
}
}
Name принимается в качестве аргументов конструктора. Когда конструктор будет использован в других частях кода, ничто не сможет изменить элемент name. Как видим, он указывается внутри, для других частей кода он недоступен.
Полиморфизм
Полиморфизм позволяет использовать одно и то же имя для решения схожих, но технически разных задач.
В примере выше находится таблица. Мы видим class CardDesk и class GraphicalObject. У обоих есть функция под названием draw(). Она выполняет разные действия, хотя имеет одно имя.
Ad hoc полиморфизм или специальный полиморфизм использует:
- перегрузку функций, методов;
- приведение типов.
Перегрузка подразумевает использование нескольких функций с одним именем, когда выбор подходящих происходит на этапе компиляции.
Приведение типов означает преобразование значения одного типа в значение другого типа. Существует явное преобразование - применяется функция, которая принимает один тип, а возвращает другой, неявное - выполняется компилятором или интерпретатором.
«Один интерфейс — много реализаций» Бьерн Страуструп.
Класс
Класс - это такой тип данных, который состоит из единого набора полей и методов.
Имеет внутренние и внешние интерфейсы для управления содержимым. При копировании через присваивание копируется интерфейс, но не данные. Разные виды взаимодействуют между собой посредством:
- наследования;
- ассоциации;
- агрегации.
При наследовании дочерний класс наследует все свойства родителя, ассоциация подразумевает взаимодействие объектов. Когда объект одного класса входит в другой, это называется агрегацией. Но когда они еще зависят друг от друга по времени жизни, - это композиция.
Одной из главных характеристик является область видимости. Понятие по-разному определяется разными ЯП.
В Object Pascal описывается следующим образом:
ClassName = class(SuperClass)
private
{ использование элементов ограничивается только пределами модуля }
{ здесь указываются поля }
strict private
{ спецификатор доступа стал доступным с выходом Delphi 2007, обозначает то же, что и private }
protected
{ элементы могут использоваться внутри ClassName или при наследовании }
public
{ }
published
{ элементы доступны всем, они отображаются в Object Inspector'e }
end;
Здесь SuperClass - предок, от которого происходит наследование.
Для C++ создание выглядит так:
class MyClass: public Parent
{
public:
MyClass(); // конструктор
~MyClass(); // деструктор
protected:
private:
};
В этом примере Parent является предком, если таковой имеется. Спецификаторы private, public, protected обозначают то же самое, что в предыдущем примере на Паскале. Также мы видим конструктор, деструктор, доступные для любой части программы. У C++ все элементы по умолчанию являются private, соответственно, это можно не указывать.
Особенности реализации
В центре объектно-ориентированных языков - объект, он является частью класса. Он состоит из:
- поля;
- метода.
Поле данных описывает параметры объекта. Они представляют собой некое значение, которое принадлежит какому-либо классу, описывают его состояние, свойства. Являются по умолчанию закрытыми, а изменение данных происходит за счет использования различных методов.
Метод - совокупность функций, которые определяют все возможные действия, доступные для выполнения над объектом. Все объекты взаимодействуют за счет вызова методов друг друга. Могут быть внешними или внутренними, что конкретизируется модификаторами доступа.
ООП-методологии
Существуют такие методологии:
- Компонентно-ориентированное программирование;
- Прототипное программирование;
- Классоориентированное программирование.
Компонентно-ориентированное программирование опирается на понятие компонента - такого составляющего программы, которое предназначено для повторного использования. Реализуется как множество конструкций с общим признаком, правилами, ограничениями. Подход используется в объектно-ориентированном языке Java, где компонентная ориентация реализуется посредством “JavaBeans”, написанных по одним правилам.
В прототипном программировании нет понятия класса - наследование производится за счет клонирования существующего прототипа. Это основа объектно-ориентированных языков javascript и других диалектов ecmascript, а также lua или lo. Главные особенности:
- потомки не должны сохранять структурное подобие прототипа (в отношении класс - экземпляр это происходит именно так);
- при копировании прототипа все методы наследуются один в один.
Классоориентированное программирование фокусируется на понятии класс и экземпляр. Класс определяет общую структуру, поведение для экземпляров, которые их перенимают.
Объектно-ориентированные языки
Все ООЯ полностью отвечают принципам ООП - элементы представляют собой объекты, у которых есть свойства. При этом, могут быть дополнительные средства.
ООЯ обязательно содержит набор следующих элементов:
- объявление классов с полями, методами;
- расширение за счет наследования функций;
- полиморфное поведение.
Кроме вышеперечисленного списка, могут быть добавлены дополнительные средства:
- конструктор, деструктор, финализаторы;
- свойства;
- индексаторы;
- модификаторы доступа.
Некоторые ООЯ отвечают всем основным элементам, другие - частично. Третьи являются гибридными, то есть совмещаются с подсистемами других парадигм. Как правило, принципы ООП могут применяться для необъектно-ориентированного языка тоже. Однако применение ООЯ еще не делает код объектно-ориентированным.
ЯП поддерживают больше, чем одну парадигму. Например, PHP или JavaScript поддерживают функциональное, процедурное, объектно-ориентированное программирование. Java работает с пятью парадигмами: объектно-ориентированной, обобщенной, процедурной, аспектно-ориентированной, конкурентной. C# считается одним из самых успешных примеров мультипарадигмальности. Он поддерживает те же подходы, что Java, к этому списку добавляется еще рефлексивная парадигма. Такой ЯП, как Oz, разработан для того, чтобы объединить все понятия, традиционно связанные с различными программными парадигмами.