Объектно-ориентированное программирование
Объектно-ориентированное программирование (ООП) - это методология программирования, при которой программа рассматривается, как набор объектов, взаимодействующих друг с другом. У каждого объекта есть набор свойств и методов.
ООП базируется на 3-х принципах:
Инкапсуляция - изоляция свойств и методов внутри объекта. Все, что необходимо объекту для его функционирования, находится внутри него. Например, если объекту требуется какая-то переменная, то она будет описана внутри него, а не снаружи в коде. Инкапсуляция позволяет скрыть некоторые свойства и методы объекта от основного кода. Например, у объекта «Повар» посетителю ресторана важен метод "Приготовить еду", но не важно, каким образом он готовит еду и какие ресурсы при этом использует.
Наследование - механизм, позволяющий создать класс, который будет содержать в себе свойства и методы другого (родительского) класса, при этом можно добавить в этот новый класс свои свойства и методы. Например, пускай есть класс «Человек». У него есть свойства, характерные для всех людей: количество глаз, рук, ног и т.д., цвет кожи, рост, вес, а также, методы "Ходить", "Говорить" и др. Предположим, мы хотим создать класс «Программист». Очевидно, что программист - это тоже человек. Поэтому он наследует все свойства от класса «Человек», но у него добавляются новые свойства и методы характерные именно для программиста, например свойство "язык программирования" и метод "писать программу".
Полиморфизм - механизм, позволяющий для одного метода, задать несколько реализаций. Например, у объекта «Человек» есть метод "работать". Однако, учитель, программист, повар будут выполнять этот метод по-разному. Полиморфизм позволяет переопределить свойства и методы, унаследованные от родительского объекта.
Выше мы использовали понятия «Класс» и «Объект». Чем они отличаются? Класс - это некое описание объекта, его "чертеж". А объект - это экземпляр класса. Например, есть понятие «Учитель» - это класс. А конкретный педагог Мария Ивановна - это объект, принадлежащий классу «Учитель» (экземпляр этого класса).
Рассмотрим программу из предыдущего урока и изменим ее таким образом, чтобы все необходимое для отображения цифры на 7-сегментном дисплее содержалось внутри класса Display7seg.

Описание класса начинается с ключевого слова class, затем идет имя класса. Тело класса заключается в фигурные скобки, после закрывающейся фигурной скобки обязательно ставится точка с запятой.
- class Display7seg
- {
- public:
- //сюда помещаются публичные свойства и методы, которые будут видны из основной программы
- private:
- //сюда помещаются свойств и методы, скрытые от внешней программы
- };//точка с запятой ставится обязательно
Наша программа с использованием класса будет выглядеть следующим образом:
- class Display7seg//создаем класс с именем Display7seg
- {
- public:
- void show(byte n)//создаем публичный (видимый) метод show, предназначенный для отображения нужной цифры.
- {
- for(byte i=0;i<8;i++)digitalWrite(i+4,bitRead(bm[n],i));
- }
- private://в этой области описываем приватное (невидимое для внешней программы, но видимое внутри класса) свойство bm - массив с конфигурациями сегментов.
- byte bm[10] = {0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00100111, 0b01111111, 0b01101111};
- };
- void setup()
- {
- for(byte i=4;i<=10;i++)pinMode(i,OUTPUT);
- }
- Display7seg D;//создаем объект D (экземпляр класса), принадлежащий классу Display7seg
- void loop(){
- for(byte i=0;i<10;i++)
- {
- D.show(i);//для вывода цифры на дисплей используем метод show объекта D.
- delay(1000);
- }
- }
Однако, наш класс Display7seg не является самодостаточным. Он сможет работать только с дисплеем, подключенным к ножкам контроллера с 4-й по 10-ю и только в правильном порядке. Кроме того, если мы забудем эти ножки сделать выходами в функции setup, то дисплей не сможет отобразить цифру. Если нам надо будет подключить дисплей к другим выводам контроллера, то нам придется переписывать класс, что крайне нежелательно.
Необходимо изменить класс таким образом, чтобы при создании объекта мы могли сообщить ему, к каким выводам контроллера подключен дисплей, и он сам делал эти ножки выходами. Для этого в любом языке программирования с поддержкой ООП имеется возможность описать конструктор класса - специальный публичный метод, который запускается автоматически при создании экземпляра класса (объекта). Конструктор в C++ описывается, как и обычная функция, только не указывается ее тип, и ее имя должно совпадать с названием класса.
Переделаем нашу программу с использованием конструктора. Конструктор примет 7 значений - номера ножек, к которым подключены сегменты дисплея от A до G, конструктор сохранит эти значения в приватном массиве pins, и дальше будет использовать эти значения.
- class Display7seg
- {
- public:
- Display7seg(byte pinA, byte pinB, byte pinC, byte pinD, byte pinE, byte pinF, byte pinG) //конструктор класса. Принимает на вход 7 чисел - номера ножек, к которым подключены сегменты дисплея
- {
- pins[0]=pinA; //сохраняем полученные числа в массив pins
- pins[1]=pinB;
- pins[2]=pinC;
- pins[3]=pinD;
- pins[4]=pinE;
- pins[5]=pinF;
- pins[6]=pinG;
- for(byte i=0; i<7; i++) pinMode(pins[i], OUTPUT); // проходим по всем сохраненным в массив номерам ножек и делаем их выходами
- }
- void show(byte n)
- {
- for(byte i=0;i<7;i++) digitalWrite(pins[i],bitRead(bm[n],i)); // номер ножки для функции digitalWrite берется из массива pins
- }
- private:
- byte bm[10] = {0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00100111, 0b01111111, 0b01101111};
- byte pins[7]; //приватный массив, в котором класс хранит номера выводов контроллера
- };
- void setup() //эта функция теперь пустая, поскольку объект сам делает нужные ножки контроллера выходами
- {
- }
- Display7seg D(4,5,6,7,8,9,10); //при создании объекта D указываем номера ножек, к которым подключен дисплей. Если мы подключим дисплей к другим ножкам контроллера, нужно будет только изменить эти цифры, не меняя при этом класс
- void loop(){
- for(byte i=0;i<10;i++)
- {
- D.show(i);
- delay(1000);
- }
- }
Теперь наш класс будет работать, не зависимо от того, к каким выводам контроллера подключен дисплей.