Файл: «Основные понятия объектно-ориентированного программирования» (Понятие об объектно-ориентированном программировании).pdf
Добавлен: 28.03.2023
Просмотров: 118
Скачиваний: 2
СОДЕРЖАНИЕ
ГЛАВА 1 ОСНОВЫ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПОДХОДА
1.1 Понятие об объектно-ориентированном программировании
1.2 Структура и способы описания языков программирования высокого уровня
1.4 Преимущества и недостатки объектно-ориентированного подхода в программировании
ГЛАВА 2 ОСНОВНЫЕ ПОНЯТИЯ ОБЪЕКТНО-ОРИЕНТИРОВАННОГО ПРОГРАММИРОВАНИЯ НА ЯЗЫКЕ С++
2.1 Базовая структура программы на С++
Синтаксис объявления класса выглядит следующим образом[15,17]:
class<имякласса>
{
private:
data members;
member functions ();
public:
data members;
member functions ();
protected:
data members;
member functions ();
};
main()
{
<name of class> obj1;
obj1.member function ();
obj1.member function();
getch();}
Class<имя класса> содержит имя, данное конкретному классу. Оно служит идентификатором, используя который можно создавать объекты.
Класс определяется ключевым словом class. Например: classDogs.
Характеристики класса описывают свойства типа данных. В классе можно объявить любое количество элементов данных любого типа. Например: floatarea;[16, 17]
С элементами данных класса могут выполняться различные операции. Можно объявить любое количество функций-членов любого типа в классе. Доступ к функциям-членам осуществляется с использованием объекта и оператора точки. Например: voidread(); voiddisplay();
Разграничения доступа используются для определения прав доступа к элементам данных и функциям класса. В зависимости от уровня доступа доступ к ним может быть разрешен или запрещен. Подробнее уровни доступа расписаны в подразделе 1.3.
Основная функция является main () – это то, где программа начинает выполнение. main () – это основная часть программы на C++, в которой обрабатываются операторы. Основная функция обычно организует на высоком уровне функциональность остальной части программы. Начинается основная программа с левой фигурной скобки – {.
Объекты класса могут быть объявлены внутри основной программы или вне ее. Объявление класса используется только для построения структуры объекта. Элементы данных и функции-члены объединяются в классе. Объявление объектов аналогично объявлению переменных базовых типов данных. Определение объектов типа данных класса известно как создание экземпляров класса. При создании объектов им выделяется память. Класс может содержать любое количество объектов[18].
Функция, определенная в классе, доступна с помощью оператора точки (.). Предположим, есть две функции класса voidread () и voiddisplay (). Необходимо получить доступ к этим функциям в основной программе.
Общий синтаксис: Obj1. Функция класса ();
Например: c1.read ();
Здесь c1 – это объект, а read () – функция класса.
Заканчивается основная программа правой фигурной скобкой – }.
Рассмотрим пример программы с классами, которая выполняет вычисление площади круга[19].
#include<iostream.h> // ссылки
#include<conio.h>// ссылки
#define PI 3.142 // область определения
float r; // область определения глобальных переменных
classCircle //определение класса Circle
{
private:
float area; // элемент данных
public:
void read() // функция класса
{
{
cout<"Enter the radius of the circle:";
cin>>r;
}
void display()
{
.area = PI * r*r;
Cout<< "Площадь круга равна" <<area;
}};
main () // главная программа
{ // начало главной программы
Circle c1;
c1.read();
c1.display();
getch();
} // конец главной программы
2.3 Наследование
Наследование является одной из ключевых особенностей объектно-ориентированного программирования на C ++. Это позволяет пользователю создавать новый класс (производный класс) из существующего класса (базовый класс). Производный класс наследует все функции от базового класса и может иметь свои собственные дополнительные функции[10].
Предположим, необходимо создать три персонажа – учитель математики, футболист и бизнесмен. Поскольку все персонажи – люди, они могут ходить и разговаривать. Тем не менее, они также имеют некоторые специальные навыки. Учитель математики может преподавать математику, футболист может играть в футбол, а бизнесмен может вести бизнес. Можно создать три разных класса, в каждом из которых, объект может ходить, разговаривать и выполнять свои специальные навыки, как показано на рис. 5[10, 11].
Рис. 5. Примеры классов
В каждом из классов нужно скопировать один и тот же код для действий перемещения и разговора. Если понадобится добавить новую функцию – например, есть, то нужно будет применить один и тот же код к каждому действующему лицу. Это может легко стать причиной ошибок (при копировании) и привести к дублированию кода. Будет проще, если создать класс Person с базовыми функциями, такими как «говорить», «ходить», «есть», «спать» и добавлять специальные навыки к этим функциям в соответствии с действующим лицом (рис. 6)[10, 11]. Выполнить это можно с помощью наследования.
Рис. 6. Схема наследования базовых действий
Используя наследование, можно не реализовывать один и тот же код для действий «ходить» и «говорить» для каждого класса. Их нужно унаследовать.
Таким образом, для учителя математики (производный класс) наследуются все функции Person (Человек) (базовый класс) и добавляется новая функция TeachMaths (Обучать математике). Аналогично, для футболиста наследуются все функции Person (Человек), и добавляется новая функция PlayFootball (Играет в футбол) и так далее. Это делает код понятным и расширяемым[12].
Правило наследования состоит в том, что каждый производный класс выходит из базового класса. В рассмотренном выше примере учитель математики – это человек, футболист – это человек, но нельзя сказать, что бизнесмен – это бизнес.
В общем виде код для рассмотренного примера имеет следующий вид[10, 11]:
class Person
{
... .. ...
};
classMathsTeacher : public Person
{
... .. ...
};
classFootballer : publicPerson
{
.... .. ...
};
В приведенном выше примере класс Person (Человек) является базовымклассом, а классы MathsTeacher (Учитель математики) и Footballer (Футболист) являются производными от Person (Человек).
Производный класс отображается с объявлением класса, за которым следует двоеточие, ключевое слово public и имя базового класса, из которого он получен[10-12].
Поскольку MathsTeacher (Учитель математики) и Footballer (Футболист) являются производными от Person (Человек), то все элементы данных и функции Person (Человек) могут быть доступны из них.
Код для базового класса Person (Человек) имеет вид:
classPerson
{
public:
string profession;
int age;
Person(): profession("profession"), age(age) { }
voiddisplay()
{
cout<<"My profession is: "<< profession <<endl;
cout<<"My age is: "<< age <<endl;
walk();
talk();
}
voidwalk(){ cout<<"I can walk."<<endl; }
voidtalk(){ cout<<"I can talk."<<endl; }
};
Код для производных классов MathsTeacher (Учитель математики) и Footballer (Футболист) имеет вид:
classMathsTeacher :public Person
{
public:
voidteachMaths(){ cout<<"I can teach Maths."<<endl; }
};
classFootballer :public Person
{
public:
voidplayFootball(){ cout<<"I can play Football."<<endl; }
};
В классе Person (Человек) два элемента – профессия и возраст. Он также содержит две функции – walk () (ходить) и talk () (говорить).
Тем не менее, MathsTeacher (Учитель математики) и Footballer (Футболист) также содержат свои собственные функции: teachMaths () и playFootball () соответственно. Эти функции доступны только их собственному классу.
2.4 Инкапсуляция
Инкапсуляцию можно определить как метод, в котором данные и функции объединяются внутри класса. Этот процесс скрывает данные, а также защищает их от доступа извне или постороннего пользователя. Чтобы получить к нему доступ, пользователь должен пройти через функции в классе.
Инкапсуляция – это концепция объектно-ориентированного программирования, которая связывает данные и функции вместе, манипулируя данными, и в конечном итоге обеспечивает защиту данных и функций от внешнего мира[10, 11].
Благодаря инкапсуляции данных стало возможным скрытие данных. C++ обычно поддерживает все свойства инкапсуляции и сокрытия данных путем создания пользовательских типов, которые называются классами. Все элементы в C ++ по умолчанию являются закрытыми.
Приведем пример инкапсуляции, в котором вычисляется объем контейнера[14].
class Box
{
public:
doublegetVolume(void)
{
return length * breadth * height;
}
private:
double length; // длина
double breadth; // ширина
doubleheight; // высота
};
Это означает, что доступ к элементам класса Box ограничен. Тем самым достигается инкапсуляция. Чтобы сделать их доступными для других участников, их нужно объявить открытыми.
Программа на C ++, в которой реализован класс с открытыми и закрытыми элементами, является примером инкапсуляции и абстракции данных[14,15].
#include<iostream.h>
classAdder{
public:
//эта часть программы доступна всем
Adder(int x = 0)
{
total = x;
}
// этотинтерфейсдоступенизвне
voidaddNum(int no)
{
total += no;
}
intgetTotal()
{
return total;
};
private:
// начиная отсюда данные скрыты
inttotal;
};
int main( )
{
Adder y;
y.addNum(10);
y.addNum(20);
y.addNum(30);
cout<< "Total " <<y.getTotal() <<endl;
return 0;
}
2.5 Абстракция
Абстракция данных может рассматриваться как процесс показа только существенной части программы внешнему миру и сокрытия деталей. Это процесс представления только необходимой информации в рамках программы и опущения деталей. Абстрагирование данных может также рассматриваться как процесс или метод, используемый для разделения интерфейса и реализации[10,12].
Например, телевизор, который мы смотрим почти каждый день. Мы знаем, как можно включать и выключать его, регулировать громкость динамика и других внешних компонентов телевизора. Но мало кто знает как работу телевизора изнутри. Как именно сигналы отправляются и принимаются, откуда они отправляются и как происходит модуляция. Все это не известно большинству.
Из этого следует, что в телевизоре можно выделить внешний интерфейс и внутреннюю реализацию. Пользователь может работать только с интерфейсом.Например, переключать каналы, увеличивать или уменьшать громкость и т. д. Это типичный пример абстракции.
В терминах C ++ классы используются для обеспечения желаемого уровня абстракции данных.
Понятия инкапсуляции и абстракции очень важны в концепции объектно-ориентированного программирования и в какой-то мере взаимосвязаны. Рассмотрим разницу между ними[12].
Инкапсуляция предполагает скрытие чего-то как в капсуле. Поэтому это больше похоже на упаковку или просто скрытие методов и свойств.
Программисты используют инкапсуляцию для скрытия данных и кодов в одном модуле с целью их защиты от внешнего мира.
Примером инкапсуляции являются классы, в то время как абстракция – это процесс показа только того, что нужно показать, и скрытие деталей от пользователя. Абстракция, как следует из названия, означает абстрактную форму вещи. Применяют абстракцию в программировании, когда нужно создать абстрактный класс, в котором представлены свойства класса и методы.
Инкапсуляция осуществляется с помощью модификаторов защищенного и закрытого доступа, а абстракция – с использованием абстрактного класса и интерфейса[10, 14].
Целостность обеспечивается в ООП с помощью инкапсуляции (то есть обеспечения надлежащего использования данных и надлежащим образом), это достигается путем предотвращения непреднамеренного доступа программистов к данным.
Отличия также поясняет пример.
Примеринкапсуляции:
Class Encapsulation
{
Private float division;
Public float division
{
get { return division; }
set {division = value;}
}
}
Примерабстракции:
abstract class Abstraction
{
public abstract void do Abstraction();
}
public class AbstractionImpl: Abstraction
{
public void doAbstraction()
{
// its Implemented it
}
}
2.6 Полиморфизм
В 1967 году Кристофером Стрейчи идентифицировал полиморфизм, а Хиндли и Милнер позже разработали это понятие. Важнымявляется не понимание реализации, а то, как работает сама концепция.
Полиморфизм – это особенность ООП, которая позволяет объекту вести себя по-разному в разных условиях. В C ++ есть два типа полиморфизма[12, 16]:
1) Полиморфизм времени компиляции – также известен как статическое (или раннее) связывание.
2) Полиморфизм времени исполнения – также известен как динамическое (или позднее) связывание.
Перегрузка функций и перегрузка операторов являются прекрасным примером полиморфизма времени компиляции.
В примере ниже есть две функции с одинаковым именем, но с разным количеством аргументов. Исходя из того, сколько параметров передается во время вызова функции, определяется, какая функция должна быть вызвана, поэтому она рассматривается как пример полиморфизма, потому что в разных условиях выходные данные различны. Поскольку вызов определяется во время компиляции, поэтому он называется полиморфизмом времени компиляции.
Пример полиморфизма времени компиляции[11,16]:
#include<iostream>
using namespace std;
class Add {
public:
int sum(int num1, int num2){
return num1+num2;
}
int sum(int num1, int num2, int num3){
return num1+num2+num3;
}
};
int main() {
Add obj;
//Вызовпервойфункции