Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Основы объекно-ориентированного программирования

Содержание:

Введение

В настоящее время объектно-ориентированный подход при разработке систем различной степени сложности общепризнан. Более того, он применяется не только при разработке, но и при использовании широко распространённых объектно-ориентированных систем. Недостатком процедурно-ориентированных языков заключается в наличии двух проблем: неограниченный доступ функций к глобальным данным и тот факт, что разделение данных и функций, которое является основой структурного подхода, плохо отображает картину реального мира [2].

Актуальность изучения концепции ООП заключается в том, что ООП является востребованной парадигмой программирования при разработке программного обеспечения, что обусловливает программисту необходимость понимания и применения ООП.

Целью работы выступает изучение парадигмы ООП, ее основных понятий и аспектов.

Задачи данной работы заключаются в том, чтобы:

  • исследовать основные понятия ООП;
  • выполнить анализ объектно-ориентированных языков программирования.

Предметом курсовой работы является объектно-ориентированное программирование.

Теоретической базой работы являются труды зарубежных и отечественных авторов, таких как: Бертран М., Буч Г., Максимчук Р. А., Энгл М. У., Янг Б. Дж., Коналлен Д., Хьюстон К. А, Лаптев В. В.

Методом исследования выступал анализ основных понятий объектно-ориентированного программирования и их взаимодействия между собой.

Структура работы - курсовая работа состоит из введения, основной части, заключения и списка используемых источников.

Глава 1. Сущность объектно-ориентированного программирования

1.1 История развития

С развитием компьютерного моделирования и усложнением моделируемых систем всё более явными становились недостатки методологий разработки программ с использованием процедурно-ориентированных языков программирования. Это объясняется отсутствием в них средств, удобных для описания сложных систем, слабой поддержкой повторной применимости ранее разработанных программ и совместных разработок коллективами программистов [1].

Объектно-ориентированное программирование (далее - ООП) (Object Oriented Programming, OOP) берёт начало в революции структурного программирования, которая происходила в шестидесятых-семидесятых годах прошлого века [3].

Первый известный объект был использован Айвеном Сазерлендом в его разработанном приложении Sketchpad в 1963 году. Объекты представляли собой графические знаки, выводимые на экране осциллографа и поддерживающие наследование через динамических делегатов, которые Айвен Сазерленд назвал в своей работе «мастер-объектами» (masters). Более того, это первый в истории случай использования графического компьютерного монитора. Любой объект мог стать мастер-объектом, дополнительные экземпляры объекта были названы «реализациями» (occurrences) [2]. Это сделало систему Sketchpad обладателем первых из известных языков программирования, который реализовал наследование.

Первым языком программирования, широко известным как именно «объектно-ориентированный», был язык Simula, спецификации которого были разработаны в 1965 году сотрудниками Норвежского вычислительного центра Оле Йохан Даль и Кристен Нюгорд. Как и Sketchpad, Silmula предусматривал работу с объектами, но также включал в себя классы, наследование, основанное на классах, подклассы, и виртуальные методы.

Виртуальным методом назывался метод, определённый в классе, который предназначался для того, чтобы подклассы его переопределяли. Виртуальные методы позволяли программам вызывать методы, которые могут не существовать на момент компиляции кода, благодаря использованию динамической диспетчеризации для определения того, какой конкретный метод нужно вызывать во время выполнения программы[3].

Понятие «объектно-ориентированное программирование» придумал Алан Кэй, имея в виду язык программирования Smalltalk в 1972 году [1]. Он разрабатывал данный язык совместно с Дэн Инглз и другими сотрудниками научно-исследовательского центра Xerox PARC в рамках проекта по созданию устройства Dynabook [2]. Язык Smalltalk был более объектно-ориентированным, чем Simula, так как в нем всё является объектом, включая классы, целые числа и блоки (замыкания). Необходимо отметить, что первоначальная реализация языка, Smalltalk-72, не имела возможностей создания подклассов. Эта возможность появилась в Smalltalk-76.

Индустрия программирования уделяет огромное внимание, созданию подклассов, отвлекаясь от настоящих преимуществ объектно-ориентированного программирования.

Другими словами, в соответствии с идеями Алана Кэя, самыми важными аспектами ООП являются [1]:

  • передача сообщений;
  • инкапсуляция;
  • позднее связывание (функции и методы можно заменять во время выполнения программы).

Вклад Smalltalk в индустрию программного обеспечения огромен. Smalltalk по-прежнему очень актуален. Он представил миру виртуальную машину VM (Virtual Machine), которая позволяет программному обеспечению быть независимым от платформы. В настоящее время эта технология используется в Java (JVM) и .NET, а также Android (Dalvik)[4].

Smalltalk был первым языком, поддерживающим «живое» программирование и усовершенствованные методы отладки, такие как проверка и изменение кода во время выполнения.

В нем появилась первая современная среда разработки, которая включала текстовый редактор, браузер системы и классов, инспектор объектов и свойств и отладчик. Это привело к созданию многих аналогичных систем, которые сегодня используют разработчики, такие как Visual Studio, Xcode и IntelliJ IDEA[3].

И в данный момент, наиболее популярными языками программирования на основании Silmula являются - С++, Delphi, C#, Java и другие, которые обеспечивают абстракцию данных и создание классов. К объектно-ориентированным же языкам относятся объектные языки, поддерживающие наследование и полиморфизм. Примерами языков, базирующихся на модели Smalltalk, являются Python и Ruby.

Таким образом, можно сделать вывод, что в наше время количество прикладных языков программирования, реализующих парадигму ООП, превышает количество языков, реализующих иные парадигмы.

1.2 Ключевые понятия ООП

Центральными понятиями в ООП являются класс и объект.

Класс — это тип, определяемый программистом, в котором объединяются структуры данных и функции их обработки. Конкретные переменные типа данных «класс» называются экземплярами класса, или объектами[7].

Класс содержит константы и переменные, называемые полями, а также выполняемые над ними операции и функции. Функции класса называются методами (другое название — функции-члены). Предполагается, что доступ к полям класса возможен только через вызов соответствующих методов. Поля и методы являются элементами (членами) класса[1].

Методы, расположенные в открытой части, формируют интерфейс класса и могут свободно вызываться клиентом через соответствующий объект класса.

Объект в ООП — некоторая сущность в виртуальном пространстве, обладающая определѐнным состоянием и поведением, имеющая заданные значения свойств (атрибутов) и операций над ними. Каждый экземпляр класса имеет уникальное для данного класса имя[3].

Объект функционирует как единое целое, реагируя соответствующими методами на соответствующие события класса. Разница между понятиями объекта и класса заключается в том, что посредством класса осуществляется описание какой-либо сущности, что работает как шаблон, основа. Например, в случае с Delphi, для того, чтобы добавить на форму кнопку, следует объявить класс, описать свойства, методы и события, и, при переносе кнопки на форму, создается экземпляр этой кнопки, т.е. объект[2].

Определенное воздействие одного объекта на другой с целью вызвать соответствующую реакцию называют операцией. В объектно-ориентированных языках программирования операции называют методами.

Можно выделить пять типов операций:

- конструктор, создание и инициализация объекта;

- деструктор, разрушающий объект;

- модификатор, изменяющий состояние объекта;

- селектор для доступа к переменным объекта без их изменения;

- итератор для доступа к содержанию объекта по частям в определенной последовательности[4].

Известна и другая классификация методов объекта, когда выделяют функции управления, реализации, доступа и вспомогательные функции.

Под индивидуальностью объекта понимают свойство объекта, позволяющее отличать этот объект от всех других объектов.

Объекты могут находиться в определенных отношениях друг к другу. Эти отношения могут быть иерархическими. Основные иерархические отношения - это отношения использования и включения. Отношение использования реализуется посылкой сообщений от объекта A к объекту B.

При этом объект A может выступать в роли:

  • активного или воздействующего объекта, когда он воздействует на другие объекты, но сам воздействию не подвергается;
  • пассивного или исполняющего, когда объект подвергается воздействию, но сам на другие объекты не воздействует;
  • посредника, если объект и воздействует и сам подвергается воздействию.

Отношение включения имеет место, когда составной объект содержит другие объекты[1].

Метод в объектно-ориентированном программировании — это функция или процедура, принадлежащая какому-то классу или объекту. Как и процедура в процедурном программировании, метод состоит из некоторого количества операторов для выполнения какого-то действия и имеет набор входных аргументов. Различают простые методы и статические методы (методы класса): простые методы имеют доступ к данным объекта (конкретного экземпляра данного класса), статические методы не имеют доступа к данным объекта и для их использования не нужно создавать экземпляры (данного класса) [7]. Методы предоставляют интерфейс, при помощи которого осуществляется доступ к данным объекта некоторого класса, тем самым, обеспечивая инкапсуляцию данных.

Немаловажно, что каждый класс должен включать в себя два обязательных метода: создать объект (конструктор), уничтожить объект (деструктор), а процесс создания объекта именуется инициализацией. Эти методы выделяют под свойства объекта память и освобождают ее, а также заполняют свойства значениями по умолчанию.

Существует так называемые права доступа, в зависимости от которых методы и классы видны другим классам [5]. В С++, например, это public, private, protected. Открытыми для доступа должны быть лишь некоторые возможности класса.

Роль классов в ООП заключается в том, что они выполняют две функции, всегда разделенные до появления объектно-ориентированных технологий: класс — это одновременно и модуль и тип [1].

Под модулями понимаются структурные единицы, из которых состоит программа. Поскольку модуль всегда рассматривается как синтаксическая концепция, то разбиение на них влияет только на форму записи исходных кодов, не определяя их функциональность. Тип — это статистическое описание определенных динамических объектов — элементов данных, обрабатываемых в процессе выполнения программы.

Примеры. Предположим, что на языке C++ нам нужно создать регистрационные записи о сотрудниках[4]. Можно сделать это следующим образом:

struct PersonnelRecord

{

char name[100];
int socialSecurityNumber;
char department[10];
float salary;

};

Каждый компонент в приведенной структуре обозначает конкретное свойство нашей абстракции регистрационной записи. Описание определяет не объект, а класс, поскольку оно не вводит какой-либо конкретный экземпляр. Для того чтобы создать объекты данного класса, необходимо написать следующее[8]:

PersonnelRecord deb, dave, karen, jim, torn, denise, kaitlyn, krista, elyse;

В данном случае объявлено девять различных объектов, каждый из которых занимает определенный участок в памяти. Хотя свойства этих объектов являются общими (их состояние представляется единообразно), в памяти объекты не пересекаются и занимают каждый свое место. На практике принято ограничивать доступ к состоянию объекта, а не делать его общедоступным, как в предыдущем определении класса [1]. С учетом сказанного, изменим данное определение следующим образом:

class PersonnelRecord

{
public:

char* employeeName() const;
int employeeSocialSecurityNumber() const;
char* employeeDepartment() const;

protected:

char name[100];
int socialSecurityNumber;
char department[10];
float salary;

};

Новое определение несколько сложнее предыдущего, но по ряду соображений предпочтительнее[5]. В частности, в новом определении реализация класса скрыта от других объектов. Если реализация класса будет в дальнейшем изменена, код придется перекомпилировать, но семантически клиенты не будут зависеть от этих изменении (то есть их код сохранится). Кроме того, решается также проблема занимаемой объектом памяти за счет явного определения операций, которые разрешены клиентам над объектами данного класса. В частности, мы даем всем клиентам право узнать имя, код социальной защиты и место работы сотрудника, но только особым клиентам (а именно, подклассам данного класса) разрешено устанавливать значения указанных параметров. Только этим специальным клиентам разрешен доступ к сведениям о заработной плате. Другое достоинство последнего определения связано с возможностью его повторного использования.

Одним из важнейших достижений в области ООП является методология паттернов проектирования, иногда называемых шаблонами проектирования [6].

Паттерн — это описание взаимодействия объектов и классов, адаптированных для решения общей задачи проектирования в конкретном контексте. [3] Паттерны выявляются по мере накопления опыта разработок, когда программист использует одну и ту же схему организации и взаимодействия объектов в разных контекстах. Паттерны предназначены, прежде всего, для инкапсуляции изменений[5].

Таким образом, можно сделать вывод, что объектно-ориентированное программирование является естественной эволюцией более ранних нововведений в разработке языков программирования и более модульным и более абстрактным, чем предыдущие попытки абстрагирования данных и переноса деталей программирования на внутренний уровень. Задача, решаемая с использованием методики объектно-ориентированного программирования, описывается в терминах объектов и операций над ними, а программа при таком подходе представляет собой набор объектов и связей между ними. Также необходимо отметить, что современное программирование базируется не только на идеях ООП, но и на применении паттернов проектирования, аккумулирующих наиболее удачные решения типичных проблем, неоднократно возникавших при разработке программного обеспечения.

Глава 2. Основные принципы структурирования

2.1. Инкапсуляция

Абстракция и инкапсуляция дополняют друг друга: абстрагирование направлено на наблюдаемое поведение объекта, а инкапсуляция занимается внутренним устройством. Чаще всего инкапсуляция выполняется посредством скрытия информации, то есть маскировкой всех внутренних деталей, не влияющих на внешнее поведение. Обычно скрываются и внутренняя структура объекта, и реализация его методов [7].

Непосредственно в описании объекта имеются только заголовки подпрограмм, а тело каждой подпрограммы задается отдельно. Описания полей всегда должны предшествовать заголовкам.

После того, как объектный тип объявлен, можно создавать переменные этого типа, или экземпляры объекта [3].

После того как экземпляр объекта создан, его поля становятся доступными для методов.

Иначе говоря, инкапсуляция – это объединение записей с процедурами и функциями, что превращает их в новый тип данных – объект [7].

То есть инкапсуляция представляет собой способности языка скрывать излишние детали реализации от пользователя объекта. Например, предположим, что используется класс по имени DatabaseReader, который имеет два главных метода: Open() и Close().

Фиктивный класс DatabaseReader инкапсулирует внутренние детали нахождения, загрузки, манипуляций и закрытия файла данных. Одним из основных особенностей данного метода является то, что он позволяет значительно сократить кодирование программы. Так как, нет необходимости прописывать дополнительно метод для реализации функционирования класса DatabaseReader, а требуется просто создать экземпляр и отправлять ему соответствующие сообщения [5].

DatabaseReader reader = new DatabaseReader.Builder("/path/to/GeoIP2-City.mmdb").build();

С идеей инкапсуляции программной логики тесно связана идея защиты данных. В идеале данные состояния объекта должны быть специфицированы с использованием ключевого слова private (или, возможно, protected). Таким образом, это позволяет защитить от несанкционированного доступа к объекту и от изменения или получение лежащего в основе значения. Это неплохой принцип, поскольку общедоступные элементы данных можно легко не преднамеренно повредить[5].

Основной единицей инкапсуляции в C# является класс, который определяет форму объекта. Он описывает данные, а также код, который будет ими оперировать. В C# описание класса служит для построения объектов, которые являются экземплярами класса. Следовательно, класс, по существу, представляет собой ряд схематических описаний способа построения объекта [4].

Код и данные, составляющие вместе класс, называют членами. Данные, определяемые классом, называют полями, или переменными экземпляра. А код, оперирующий данными, содержится в функциях-членах, самым типичным представителем которых является метод. [3] В C# метод служит в качестве аналога подпрограммы. К числу других функций-членов в свою очередь относятся свойства, события и конструкторы. Следовательно, методы класса содержат код, воздействующий на поля, определяемые этим классом.

Следовательно, инкапсуляция представляет собой объединение данных и обрабатывающих их методов (подпрограмм) внутри класса (объекта). Это означает, что в классе объединяются и помещаются внутрь поля, свойства и методы. При этом класс получает определенную функциональность, например, обеспечивая полный набор средств, для создания программы поддержки некоторого элемента интерфейса (окна Windows, редактора и т. п.) или прикладной обработки.

2.2. Наследование

Наследование — это процесс порождения новых объектов-потомков от существующих объектов-родителей, при этом потомок наследует от родителя все его поля, свойства и методы. В дальнейшем наследуемые поля, свойства и методы можно использовать в неизменном виде или переопределять (модифицировать)[7].

Просто наследование большого смысла не имеет, поэтому в объект-потомок добавляются новые элементы, определяющие его особенность и функциональность. Удалить какие-либо элементы родителя в потомке нельзя. В свою очередь, от нового объекта можно породить следующий объект, в результате образуется дерево объектов (называемое также иерархией классов).

Наследование – это использование объекта для построения иерархии порожденных объектов с наследованием доступа каждого из порожденных объектов к коду предка.

Существует тип, служащий основой для создания нового объекта, называемый предком или родительским типом, а создаваемый объект – потомком или дочерним типом [8]. Благодаря наследованию на основе существующего объекта можно создать любое количество новых объектов.

В качестве примера рассмотрим следующую иерархическую зависимость, которая представлена в приложении 1, где показана структура программы, описывающая характеристики машины.

Класс «MySportCar» - это общая часть класса «MyCar», в свою очередь «MyCar» является частью еще более общего класса объектов «Program». Каждый раз порожденный класс наследует все, связанное с родителем, и добавляет к ним свои собственные определяющие характеристики.

То есть наследование представляет собой процесс, в ходе которого один объект приобретает свойства другого объекта. Это очень важный процесс, поскольку он обеспечивает принцип иерархической классификации.[2]

Если не пользоваться иерархиями, то для каждого объекта необходимо явно определять все его свойства. А если воспользоваться наследованием, то достаточно определить, лишь определенные характеристики, которые делают объект особенным в его классе. Он может также наследовать общие свойства своего родителя. Следовательно, благодаря механизму наследования один объект становится отдельным экземпляром более общего класса [3].

Немало важную роль в наследовании играют модификаторы доступа, которые позволяют организовать иерархию объектов.

Используя public-наследование, потомкам передаётся всё, что есть в основном классе, в таком виде, как и записано в основном классе. В итоге образуется дубликат основного класса. Разница в том, что элементы основного класса к элементам данного дубликата отношения не имеют.

Используя private-наследование, можно создать первого потомка, от которого дальнейшее наследование будет бессмысленно. Если первый потомок получает возможность работы с некоторыми элементами, переданными по механизму наследования, то потомки первого потомка таких возможностей не получают. Кроме того, потомки первого потомка даже лишены возможности узнавать, кто их первый родитель[1].

Использованием protected-наследования программистом предполагается, что внутри всех потомков будут использоваться только такие элементы, передаваемые механизмом наследования, которые будут защищены от влияния на себя извне своих классов[3].

Таким образом, процесс, с помощью которого один тип наследует характеристики другого типа, называется наследованием. Наследование объектов аналогично общепризнанному понятию наследования, когда определяется новый объект, как потомок уже существующего объекта, то утверждается, что потомок по большей части такой же, как и предок. К объекту-потомку в случае необходимости могут быть объявлены новые поля, новые методы и перекрыты уже существующие методы предка. Эти добавления и изменения определяют только то, в чем потомок отличается от предка.

2.3. Полиморфизм

Полиморфизм — присваивание действию одного имени, которое затем совместно используется вниз и вверх по иерархии объектов, причем каждый объект иерархии выполняет это действие способом, именно ему подходящим [9]. «Полиморфизм» представляет собой способность обладать несколькими формами, отмечается автором [1]. В объектно-ориентированной разработке это относится к сущностям (элементам структур данных), способным в процессе выполнения присоединяться к объектам разных типов.

Полиморфизм дает возможность применения одних и тех же функций для решения различных задач и находит свое отражение в том, что под одним именем содержатся разные действия, наполнение которых зависит от типа объекта. Производные одного базового класса считаются полиморфными. Это подразумевает, что им присущи как общие характеристики, так и собственные свойства. Касательно средств, которые связаны с возможностью реализации полиморфизма, то следует упомянуть следующие виды методов в ООП[3].

Во-первых, это статические методы класса включаются в код программы в процессе ее компиляции. Таким образом, до запуска программы уже известно, какая процедура будет вызвана в определенной точке, происходит так называемое раннее связывание (Early binding). То есть ситуация, при которой адрес вызываемого метода известен уже в момент компоновки[4].

Во-вторых, это виртуальные методы, которые подключаются к основному коду на этапе выполнения программы и дают возможность определить тип и конкретизировать экземпляр объекта в процессе исполнения, а затем вызвать методы этого объекта. Данный механизм именуется также поздним связыванием (Late binding). Это ситуация, при которой адрес вызываемого метода неизвестен до момента выполнения программы. Адресация разрешается путем использования таблиц виртуальных методов с адресами методов.

Реализация позднего связывания в языке программирования позволяет создавать переменные − указатели на объекты, принадлежащие различным классам (полиморфные объекты), что существенно расширяет возможности языка.

Термины «раннее связывание» и «позднее» относятся к этапу, на котором обращение к процедуре связывается с ее адресом. В случае раннего связывания адреса всех функций и процедур известны в тот момент, когда происходят компиляция и компоновка программы. Это позволяет приписать каждому обращению к процедуре соответствующий адрес. В большинстве традиционных языков, включая С и Паскаль, используется только раннее связывание.[8] В противоположность этому, в случае позднего связывания адрес процедуры не связывается с обращением к ней до этого момента, пока обращение не произойдет фактически, т.е. во время выполнения программы.

Полиморфизм – задание одного имени действию, которое передается вверх и вниз по иерархии объектов с реализацией этого действия способом, соответствующим каждому объекту в иерархии [7].

Рассмотрим для примера стек, т.е. область памяти, функционирующую по принципу «последним пришел — первым обслужен». Допустим, что в программе требуются три разных типа стеков: один — для целых значений, другой — для значений с плавающей точкой, третий — для символьных значений. В данном примере алгоритм, реализующий все эти стеки, остается неизменным, несмотря на то, что в них сохраняются разнотипные данные. В языке, не являющемся объектно-ориентированным, для этой цели пришлось бы создать три разных набора стековых подпрограмм с разными именами. Но благодаря полиморфизму для реализации всех трех типов стеков в C# достаточно создать лишь один общий набор подпрограмм [4]. Зная, как пользоваться одним стеком, вы сумеете воспользоваться и остальными.

В более общем смысле понятие полиморфизма нередко выражается следующим образом: «один интерфейс — множество методов». Это означает, что для группы взаимосвязанных действий можно разработать общий интерфейс. Полиморфизм помогает упростить программу, позволяя использовать один и тот же интерфейс для описания общего класса действий. Выбрать конкретное действие (т.е. метод) в каждом отдельном случае — это задача компилятора. Программисту не нужно делать это самому. Ему достаточно запомнить и правильно использовать общий интерфейс[5].

Полиморфизм это возможность объектов с одинаковой спецификацией иметь различную реализацию.

Язык программирования поддерживает полиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию — например, реализация класса может быть изменена в процессе наследования[1].

Полиморфизм позволяет писать более абстрактные программы и повысить коэффициент повторного использования кода. Общие свойства объектов объединяются в систему, которую могут называть по-разному — интерфейс, класс.

Практический смысл полиморфизма заключается в том, что он позволяет посылать общее сообщение о сборе данных любому классу, причем и родительский класс, и классы-потомки ответят на сообщение соответствующим образом, поскольку производные классы содержат дополнительную информацию. Программист может сделать регулярным процесс обработки несовместимых объектов различных типов при наличии у них такого полиморфного метода[3].

Полиморфизм, может быть, достигнут двумя способами:

  • переопределение метода;
  • перегрузка метода.

Переопределением (override) называют такую перегрузку методов, когда в классах, связанных отношением наследования, существуют методы с одинаковыми именами, количеством и типом параметров[6].

Рассмотрим на примере языка Java, который представлен в приложении 2.

Существует родительский класс A, в нем определен метод message(). В подклассе В родительский метод переопределен.

Запись @Override называется аннотацией и указывает, что метод базового класса должен быть переопределен. Если в базовом классе не окажется метода с аналогичной сигнатурой, то мы получим предупреждение компилятора о том, что метод переопределить невозможно. Аннотация не влияет на переопределение метода, но служит лишь для контроля успешности переопределения. Аннотацию можно удалить, но этого делать не надо, потому что в случае ошибки вместо переопределения будет выполнена перегрузка метода[1].

Таким образом, при переопределении методы должны иметь одинаковые сигнатуры и переопределяться могут только наследованные методы.

Перегрузка метода (overload) означает запись двух или более методов в одном классе с использованием того же имени метода, но параметры передачи отличаются. То есть она позволяет использовать одно и то же имя для нескольких методов с разными сигнатурами[3].

То есть, для перегрузки методов необходимо определить методы с одним и тем же именем, которые отличаются: количеством параметров, типом параметров, последовательностью типов параметров. Так как в процессе компиляции определяется, какой метод следует вызвать, основываясь на этих свойствах. Необходимо отметить, что имена параметров, тип возвращаемого значения и модификатор доступа метода в выборе требуемого метода не участвуют.

Итак, можно сделать вывод, что сущность полиморфизма заключается в том, что методы различных классов могут иметь одинаковые имена, но различное содержание. Это достигается переопределением родительского метода в классе-потомке: В результате родитель и потомок ведут себя по-разному. При этом обращение к одноименным методам различных объектов выполняется аналогично.

Из выше сказанного следует вывод, что основными характеристическими свойствами объектно-ориентированного программирования являются:

  • Инкапсуляция - комбинирование записей с процедурами и функциями, манипулирующими полями этих записей, формирует новый тип данных - объект (под записью понимается переменная типа "запись").
  • Наследование - определение объекта и его дальнейшее использование для построения иерархии порожденных объектов с возможностью для каждого порожденного объекта, относящегося к иерархии, доступа к коду и данным всех порождающих объектов.
  • Полиморфизм - присваивание действию одного имени, которое затем совместно используется вниз и вверх по иерархии объектов, причем каждый объект иерархии выполняет это действие способом, именно ему подходящим.

Глава 3. Анализ объектно-ориентированные языков программирования

3.1 C++

История создания С++ начинается с языка С. С++ можно назвать расширенной и улучшенной версией языка С. В сравнении с его предшественником, наибольшее внимание уделено поддержке объектно-ориентированного и обобщённого программирования.

Язык С++ был создан Бьерном Страуструпом в 1979 году в компании Bell Laboratories [5]. Сначала новый язык получил имя «С с классами», но в 1983 году он стал называться С++.

В 1997 году был принят международный стандарт С++, который обеспечил единообразие всех реализаций языка.

Язык С++ является универсальным языком программирования, в дополнение к которому разработан набор разнообразных библиотек.

Необходимо отметить, что он используется практически во всех областях науки, техники и производства.[4] Он позволяет удобно, эффективно и быстро разрабатывать программы, тестировать и изменять их. Его применяют для решения множества технических, научных и инженерных задач, а также для создания программ широкого пользования.

Этот язык программирования в настоящее время является одним из наиболее распространенных языков программирования в мире [8].

Текущий стандарт языка ISO/IEC 14882:2017 был опубликован в декабре 2017 года. Неофициально его обозначают как C++17. Следующая версия стандарта, запланированная на 2020 год, имеет неофициальное обозначение C++20.

Рассмотрим простой пример программы, который выводит сообщение «Hello, world!», используя стандартную библиотеку, и завершается.

#include <iostream>

using namespace std;

int main()

{

count << “Hello, world!” << end;

return 0;

}

При проектировании С++ Бьерн Страуструп придерживался следующим принципам и задачам, подтверждающие особенности данного языка программирования [8]:

  • получить универсальный язык со статическими типами данных, эффективностью и переносимостью языка С;
  • иметь возможность поддерживать множество стилей программирования, в том числе процедурное программирование, абстракцию данных, объектно-ориентированное программирование и обобщённое программирование;
  • программист должен иметь свободу выбора, даже если он будет неверным;
  • для быстрого и легкого перехода от языка программирования С, попытаться максимально сохранить совместимость с ним;
  • необходимо избежать разночтений между С и C++, то есть любая конструкция, допустимая в этих языках, должна обозначать одно и то же и приводить к одинаковому результату программы[4];
  • избегать особенностей, которые зависят от платформы или не являются универсальными;
  • программирование на С++ не должно приводить к снижению производительности программы;
  • не требовать слишком усложнённой среды программирования.

В настоящее время, многие программисты отмечают, что все эти принципы данного языка программирования реализованы, что делает его достаточно популярным в сфере информационных технологий[5].

3.2 Java

Java — объектно-ориентированный язык программирования, который разработала компания Sun Microsystems. Официальная дата выпуска является 23 мая 1995 года [6].

Объекты в Java представляют собой экземпляры класса. Работает на различных платформах, таких как Windows, Mac OS, а также различных версий UNIX.

Принцип работы приложений на Java заключается в том, что они транслируются в байт-код, который выполняется специальной виртуальной машиной (JVM), где она является программой, обрабатывающей байтовый код и передающей инструкции оборудованию как интерпретатор.

Основным преимуществом такого способа выполнения программ является то, что байт-код не зависит от операционной системы и оборудования, что позволяет выполнять Java-приложения на любом устройстве, для которого существует соответствующая виртуальная машина. Другой важной особенностью технологии Java является гибкая система безопасности из-за того, что её исполнение полностью контролируется виртуальной машиной [6]. То есть, если какая-то операция превышает установленные полномочия программы, то происходит немедленное прерывание цикла. К таким операциям можно отнести - попытку несанкционированного доступа к данным или соединения с другим компьютером.

Часто к недостаткам концепции виртуальной машины относят то, что исполнение байт-кода виртуальной машиной может снижать производительность программ и алгоритмов, реализованных на языке Java. Как отмечают некоторые программисты, что время выполнения программ на Java в среднем в полтора-два раза больше, чем для C/C++[4].

Данное утверждение было справедливо для первых версий виртуальной машины Java, но в последнее время эта проблема практически теряет актуальность. В связи с некоторыми усовершенствования, такими как:

  • применение технологии трансляции байт-кода в машинный код непосредственно во время работы программы (JIT-технология) с возможностью сохранения версий класса в машинном коде,
  • широкое использование платформенно-ориентированного кода (native-код) в стандартных библиотеках,
  • аппаратные средства, обеспечивающие ускоренную обработку байт-кода (например, технология Jazelle, поддерживаемая некоторыми процессорами фирмы ARM).

Необходимо отметить, что идеи, заложенные в концепцию и различные реализации среды виртуальной машины Java, вдохновили множество энтузиастов на расширение перечня языков, которые могли бы быть использованы для создания программ, исполняемых на виртуальной машине. Эти идеи нашли также выражение в спецификации общеязыковой инфраструктуры CLI, заложенной в основу платформы.NET компанией Microsoft [2].

Внутри Java существуют несколько основных семейств технологий:

  • J2EE или Java EE (начиная с v1.5) — Java Enterprise Edition, для создания программного обеспечения уровня предприятия;
  • J2ME, Java ME или Java Micro Edition, для использования в устройствах, ограниченных по вычислительной мощности, в том числе мобильных телефонах, КПК, встроенных системах;
  • Java Card для использования в устройствах без собственного человеко-машинного интерфейса, например в смарт-картах.

Самыми известными и часто используемыми в сфере информационных технологий считаются серверные технологии семейства J2EE [5].

Выделяют следующие возможности языка программирования[6]:

  • автоматическое управление памятью;
  • расширенные возможности обработки исключительных ситуаций;
  • богатый набор средств фильтрации ввода-вывода;
  • набор стандартных коллекций: массив, список, стек и т. п;
  • наличие простых средств создания сетевых приложений (в том числе с использованием протокола RMI).
  • наличие классов, позволяющих выполнять HTTP-запросы и обрабатывать ответы;
  • встроенные в язык средства создания многопоточных приложений, которые потом были портированы на многие языки (например Python).
  • унифицированный доступ к базам данных, а именно на уровне отдельных SQL-запросов — на основе JDBC, SQLJ и на уровне концепции объектов, обладающих способностью к хранению в базе данных — на основе Java Data Objects (англ.) и Java Persistence API;
  • поддержка обобщений (начиная с версии 1.5);
  • поддержка лямбд, замыканий, встроенные возможности функционального программирования (с версии 1.8).

Рассмотрим пример использования данного языка программирования, который создаёт надпись «Hello World!».

Class NewClass {

Public static void main (String[] args)

{

System.out.println (“Hello World!”)

}

}

Успешные и известные проекты, реализованные с привлечением Java (J2EE) технологий, считаются - RuneScape, Amazon, eBay, LinkedIn, Yahoo!.

В настоящее время компании, которые в основном фокусируются на Java (J2EE) технологиях: SAP, IBM, Oracle. В основном, СУБД Oracle Database включает JVM как свою составную часть, обеспечивающую возможность непосредственного программирования СУБД на языке Java, включая, например, триггера [5].

3.3 Язык Python

Язык Python получил широкое распространение в сфере информационных технологий за счет своей простоты в изучении и использовании. Программный код на языке Python легко читать и писать, так как он не содержит сложного синтаксиса. Так же он позволяет уместить приложение в меньшее количество строк, чем на это потребовалось бы в других языках, таких как C++ или Java [4].

История этого языка программирования начинается в конце 1980-х годов сотрудником голландского института CWI (Центр математики и информатики, голл. Centrum Wiskunde & Informatica) Гвидо ван Россумом (англ. Guido van Rossum), на основе языка ABC.

На создания Python повлияли ранее созданные языки программирования такие, как:

  • язык ABC: отступы для группировки операторов, высокоуровневые структуры данных;
  • Modula-3: пакеты, модули;
  • С, C++: некоторые синтаксические конструкции;
  • Smalltalk: ООП [1];
  • Java: обработка исключений и др.

Также большая часть других особенностей Python (например, байт-компиляция исходного кода) также была реализована ранее в других языках.

Необходимо отметить, что развитие языка происходит согласно четко регламентированному процессу создания, обсуждения, отбора и реализации документов PEP (Python Enhancement Proposal) — предложений по развитию Python [9].

Можно выделить следующие особенности, которые отмечают в Python. Во-первых, он несложный язык программирования, что дает возможность сосредоточиться на решении задачи, а не на самом языке. Во-вторых, у него существует возможность встраиваться в программы на C/C++, чтобы предоставлять возможности написания сценариев их пользователям или для ускорения работы программы. В-третьих, Python поставляется по принципу «все включено» (англ. Batteries Included) и имеет обширные возможности в стандартной библиотеке в дополнение к встроенным возможностям языка.[4] Где, в свою очередь, стандартная библиотека позволяет решать различные задачи, связанные с использованием регулярных выражений, генерацией документации, проверкой блоков кода, распараллеливанием процессов, базами данных, сетью Интернет, электронной почтой, криптографией, GUI (графическим интерфейсом пользователя) и другим системно-зависимым функционалом. В-четвертых, Python является свободным и открытым программным обеспечением (Free/Libré and Open Source Sotware – FLOSS).

3.4. С#

С# был разработан Андерсом Хейлсберг. Он также является создателем компилятора, который лег в основу Turbo Pascal и языка программирования Delphi. Запуск первой версии языка произошла в июне 2000 года, а окончательная версия вышла в 2002 году вместе с Visual Studio. Сейчас C# стал одним из самых популярных языков программирования объектно-ориентированного программирования[7].

Необходимо отметить, что большинство понятий и конструкций заимствованы из других языков, таких как С, С++, Java и.т.д. Первые версии языка были очень похожи на Java, однако в данный момент C# уже нельзя считать просто копией этого языка, настолько сильно он стал развиваться.

C# нельзя рассматривать только как язык, это часть большой системы, которая включает в себя ОС Windows, среду разработки Visual Studio и другие инструменты, ну и, конечно, саму Microsoft, которая обеспечивает поддержку этого языка [10].

Что касается применения, то поскольку язык принадлежит компании Майкрософт, то соответственно и используется он практически во всех продуктах, которые были разработаны или куплены. Рассмотрим наиболее известные из них.

Mono – это проект, который был посвящен свободной реализации C# и .NET. На основе Mono была создана XamarinStudio, которая позволяет создавать мобильные приложения на C#, не используя платформы Java и Objective-C. Была выкуплена у автора Мигеля де Иказа и внедрена в Visual Studio [1].

DirectX – API (Application Programming Interface) для программирования под Windows, чаще всего используется при разработке игр.

Unity – кросс-платформенная игровая утилита, которая позволяет создавать двухмерные и трехмерные игры. Было отмечено, что широко используется среди индийских разработчиков, однако также распространена среди крупных компаний. Так, например, Hearthstone создан на основе Unity.

Также, рассмотрим сопутствующие технологии данного языка программирования [10]:

  • LINQ (Language Integrated Query) - язык интегрированных запросов, напоминающий SQL, в языках для платформы .NET.
  • Microsoft Visual Studio - один из самых известных продуктов от Microsoft. Среда разработки, которая позволяет писать код на C#, С++ и некоторых других (при установке специальных утилит).
  • ASP.NET - технология для веб-приложений (и сервисов), продолжение старой технологии ASP (Active Server Pages).
  • TPL (Task Parallel Library) - библиотека для создания многопоточных приложений.
  • WCF(Windows Communication Foundation) - среда выполнения и набор API-интерфейсов для создания систем, которые обеспечивают обмен сообщениями между службами и клиентами[4].
  • WPF (Windows Presentation Foundation) - система для построения приложений с визуальный интерфейсом для Windows, которая позволяет добавлять двухмерную трехмерную графику, анимацию и.т.д.
  • Resharper – специальная программа для Visual Studio, который позволяет обеспечивает дополнительные функции при написании кода, выявления ошибок, улучшенную навигацию по коду и статический анализ кода без выполнения программы.
  • F# - язык для функционального программирования под .NET

На сегодняшний день практически все объектно-ориентированные языки программирования являются развивающимися языками, их стандарты регулярно уточняются и расширяются. Следствием этого развития являются неизбежные различия во входных языках компиляторов различных систем программирования. Наиболее распространенными в настоящее время являются системы программирования Microsoft C++ , Microsoft Visual C++ и системы программирования фирмы Borland International.

Заключение

В ходе выполнения работы можно выделить следующие выводы.

Во-первых, появление парадигмы ООП обусловливалось необходимостью решения возникающих проблем при построении сложных программных систем. Наиболее важными событиями, связанными с историей ООП считаются появление языка Simula, содержащего базовые аспекты ООП, а также возникновение языка Smalltalk — первого объектно-ориентированного языка программирования.

Во-вторых, многие языки объектно-ориентированного программирования являются развивающимися, так как их стандарты постоянно расширяются. В настоящее время наиболее известные это С++, Java, Python, С#.

На основании полученной информации, можно сказать, что основными понятиями объектно-ориентированного языка программирования являются: класс, объект, метод, свойство, поле. А также - наследование, полиморфизм, инкапсуляция.

Библиография

  1. Бертран М. Основы объектно-ориентированного программирования [Электронный ресурс] / Бертран М. — Электронное издательство «Интернет-университет информационных технологий — ИНТУИТ.ру», 2015 г.
  2. Буч Г., Максимчук Р. А., Энгл М. У., Янг Б. Дж., Коналлен Д., Хьюстон К. А. Объектно-ориентированный анализ и проектирование с примерами приложений — 3-е изд. — М.: ООО «И. Д. Вильямс», 2018
  3. Гама Э., Хелм Р. Приемы объектно-ориентированного проектирования. Паттерны проектирования. — СПб.: Питер, 2018
  4. Лаптев В. В. С++. Объектно-ориентированное программирование: Учебное пособие/ В. В. Лаптев. — СПб.: Питер, 2016
  5. Лафоре Р. Объектно-ориентированное программирование в C++. — 4-е изд. — СПб.: Питер, 2015
  6. Медведев В. И. Особенности объектно-ориентированного программирования на C++/CLI, C# и Java. — 2-е изд., испр. и доп. — Казань: РИЦ «Школа», 2010
  7. Мейер Б. Объектно-ориентированное конструирование программных систем. — М.: Наука, 2015
  8. Павловская Т. А., Щупак Ю. А. C/C++. Структурное и объектно-ориентированное программирование: Практикум. — СПб.: Питер, 2017
  9. Фёдоров Д. Ю. Основы программирования на примере языка Python / Учебное пособие. — СПб.: Юрайт, 2018
  10. Эндрю Троелсен. Язык программирования C# 5.0 и платформа .NET 4.5, 6-е издание = Pro C# 5.0 and the .NET 4.5 Framework, 6th edition. — М.: «Вильямс», 2013

Приложения

Приложение 1

Рисунок 1. Пример наследования

Приложение 2

Рисунок 2. Пример переопределения в полиморфизме