Close

Objektově orientované programování I. – Úvod

Programovací jazyky - Wordcloud - Zdroj Wikipedia Commons

V prvním článku ze seriálu věnovanému programování obecně jsme si popsali různé typy programovacích jazyků a ukázali jsme si, jak přibližně vypadají programy v nich napsané. Také jsme došli k tomu, že C++, ve kterém se běžně Arduino programuje, je objektově orientovaný jazyk. A právě objektově orientovaným programováním se dnes budeme zabývat.


Některé z vás jsem teď možná zmátl. Tvrdím, že Arduino se běžně programuje v C++. V předchozích článcích jsem ale tvrdil, že Arduino programujeme v jazyce Wiring. Skutečnost je taková, že Wiring je knihovna pro jazyk C++, která zjednodušuje programování Arduina. Jelikož běžný uživatel Arduina většinou neví, jaká konstrukce pochází z C++ a jaká je specifická pro Wiring, ujalo se v Arduino komunitě pojmenování jazyk Wiring. To je sice z technologického hlediska nesprávné označení, ale pro naše účely není nutné mezi C++ a Wiring přesně rozlišovat.

Objektově orientované programování

Základním prvkem objektově orientovaných (dále OO) jazyků je objekt. Objekt si můžeme představit jako konkrétní věc – například psa Alíka. Abychom mohli takovéto objekty vytvářet, potřebujeme nějaký vzor – řekněme vzor, který si nazveme pes. Takovému vzoru se v OO programování říká třída. Ta nám definuje vlastnosti (atributy) a schopnosti (metody) objektu. Podle třídy pes je možné vytvořit libovolné množství psů – psa Alíka, psa Žeryka, psa Punťu… Těmto konkrétním objektům se říká také instance třídy pes. Jak by mohla vypadat třída pes? Třeba takto:

class Pes{      private:           String jmeno = "";          int vyska = 0;        public:           Pes(String, int);          void stekej();  }; //tady opravdu musí být středník!  

Odbočka do terminologie. Funkcím, které náleží objektu se říká metody. Proměnným, které náleží objektu se říká atributy.

Máme tedy objekt pes, který má atributy jmenovyska a umí štěkat pomocí metody stekej. Všimněte si, že jmeno a vyska jsou uvozené klíčovým slovem private. Tyto proměnné jsou označeny za „soukromé“. Bude k nim možné přistupovat pouze uvnitř metod objektu. Naopak klíčové slovo public označuje atributy a metody, které jsou dostupné i vně objektu – tedy je možné je volat v rámci programu. Metoda Pes() (která má stejný název, jako objekt samotný) je speciální a říká se jí konstruktor. Pomocí konstruktoru dochází k vytváření nových instancí třídy Pes. V rámci konstruktoru můžeme například nastavit hodnoty privátních atributů podle parametrů konstruktoru a podobně. Konstruktor se definuje takto:

Pes::Pes(String jm, int vy){      jmeno = jm;       vyska = vy;  }  

Atributy vytvořené instance třídy Pes se nastaví na zadané hodnoty. Ještě nám zbývá vytvořit metodu stekej.

void Pes::stekej(){      Serial.print(jmeno);      Serial.print(" steka ");      Serial.println("Haf!");     }  

Nyní tedy máme šablonu, podle které můžeme vytvořit různé konkrétní psy.

Pes alik("Alik", 100); //pes Alik vysoký 100cm  Pes zeryk("Zeryk", 60); //pes Zeryk vysoký 60cm  

A ještě zbývá psy trochu popíchnout, aby zaštěkali.

alik.stekej();  zeryk.stekej();  

Celý program, který nechá psy zaštěkat, tedy vypadá následovně:

class Pes{      private:           String jmeno = "";          int vyska = 0;        public:           Pes(String, int);          void stekej();  }; //tady opravdu musí být středník!    Pes::Pes(String jm, int vy){      jmeno = jm;       vyska = vy;  }    void Pes::stekej(){      Serial.print(jmeno);      Serial.print(" steka ");      Serial.println("Haf!");     }    Pes alik("Alik", 100);  Pes zeryk("Zeryk", 60);    void setup() {      Serial.begin(9600);      Serial.println("Smecka");        alik.stekej();      zeryk.stekej();  }    void loop() {    }  

Praktický příklad

Možná si říkáte, že je sice hezké, že máme vytvořenou třídu Pes, ale k čemu nám je u Arduina platná? Ukažme si tedy nějaký jednoduchý praktický příklad.

class LED{      private:           int pin;          boolean stav = LOW; //výchozí stav LED je vypnuto          void nastav(boolean);        public:           LED(int);          void zapni();          void vypni();          void prepni();          boolean vratStav();  };    LED::LED(int p){      pin = p;      pinMode(pin, OUTPUT);      digitalWrite(pin, stav);  }    void LED::zapni(){      nastav(HIGH);  }    void LED::vypni(){      nastav(LOW);      }    void LED::prepni(){      nastav(!stav); //nastaví LED na obrácenou hodnotu (0->1, 1->0)  }    void LED::nastav(boolean s){      stav = s;      Serial.print("Nastavuji ");      Serial.print(stav);      Serial.print(" na pinu ");      Serial.println(pin);      digitalWrite(pin, stav);  }    boolean LED::vratStav(){      return stav;       }    LED L13(13);    void setup() {      Serial.begin(9600);      L13.zapni();      delay(1000);      L13.vypni();      delay(1000);      for(int i = 0; i <= 10; i++){          L13.prepni();          delay(500);          }        Serial.print("Led zustala ve stavu ");      Serial.println(L13.vratStav());  }    void loop() {  }  

Jedná se o velice jednoduchou třídu sloužící k ovládání LED diody. Její public metody jsou zapni, vypni, prepni a vratStav (jejich název je snad dostatečně popisný :) ).  Všimněte si, že třída LED obsahuje i private metodu nastav, která slouží k  nastavení stavu LED a zároveň k výpisu stavu na sériovou linku. Metoda nastav je volána uvnitř jiných metod třídy LED. Také je zde předvedena technika, která se používá k získání hodnot privátních atributů objektů. Přímo k atributu stav bychom se totiž pomocí L13.stav nedostali, proto musíme využít nějakou public metodu.

To byl letmý úvod do OO programování. O jeho dalších principech více zase příště.

Zbyšek Voda

12 Comments on “Objektově orientované programování I. – Úvod

Profilový obrázek
BorgMcz
20.6.2016 at 21:03

Já bych se dovolil zeptat, na jednu věc, která by mohla být dnešnímu tématu blízká.
Potřeboval bych v jednom projektu v následujícím kódu měnit v posloupnosti jméno :
RBD::Button jméno (pin);
toto je základní vytvoření funkce, mohu ji tvořit ručně ale protože kód bude složitější a bude se mnohokrát opakovat a tak hledám jak jinak na to: ručně to udělám takto:

RBD::Button jmeno0 (30);
RBD::Button jmeno1 (31);
RBD::Button jmeno2 (32);
ale potřeboval bych to tvořit automaticky za pomoci cyklu, něco jako asi takhle:

for (int x=0; x<15; x++) {
RBD::Button jmeno(x) (y);
}
nevím, jak správně to zapsat, aby IDE pochopilo co chci. Dá se to nějak zapsat?
Jde mi pouze o to jméno plus číslo v X , Y je jasné.

Zbyšek Voda
Zbyšek Voda
20.6.2016 at 21:13

Dobrý den. Toto budu probírat v jednom z dalších článků. Zatím vas nasměruji, kde hledat – podívejte se, jak se vytváří v C++ pole objektů a uložte si jednotlivá tlačítka do pole :)

Profilový obrázek
BorgMcz
21.6.2016 at 6:19

To jsem zkoušel, zjevně ale nesprávným zápisem. U toho Y kde dosazuji přiřazené piny (tedy jen čísla) mi to funguje, ale ne pro ten název. Nemohl bych poprosit o pomoc třeba na mailu? mm.svet(zavi.nač)centrum.cz
Diky.

Zbyšek Voda
Zbyšek Voda
21.6.2016 at 13:06
Profilový obrázek
BorgMcz
21.6.2016 at 21:10

Rekl bych, že ted v tom mam jeste vetsi zmatek nez predtim :-)) Mohl bych poprosit o kontakt pres mail?

Zbyšek Voda
Zbyšek Voda
22.6.2016 at 8:28
Profilový obrázek
tribal.cz
20.6.2016 at 16:49

Zbyšku nádhera, ale nemohu se ubránit dojmům jako překvapení a zmatenost. Jak dlouho lze arduino programovat pomocí OOP? Jedná se o funkci přidanou někdy v poslední době? ani ne před půl rokem jsem se o to zajímal na jednom fóru (pravda nikdy jsem to nezkusil), a odpovědí mi byl imaginární výsměch nejméně tří až čtyř členů daného fóra. Prakticky mi bylo řečeno že pokud chci programovat objektově mám zapomenout na arduino a vrátit se k vyšším jazykům.

Zbyšek Voda
Zbyšek Voda
21.6.2016 at 10:33

Dobrý den, nerad bych plácnul nějakou blbost, ale myslím, že Arduino toto podporuje od začátku – knihovna Wiring je na C++, které objekty přímo podporuje. C++ nakonec stejně skončí v podobě nul a jedniček, takže nevidím důvod, proč by to nemělo jít :)

Objekty jsou většinou dostupné v knihovnách pro obsluhu všeho možného (ethernnet, motory, senzory…), takže se uživatel většinou s definováním objektů nesetká, ale jen je používá.

Profilový obrázek
Melas
19.6.2016 at 20:06

Zábavnou formou vysvětlená problematika. Je pravda, že jsou funkce, které používám, ale ve skutečnosti jim nerozumím a tohle mi je osvětluje. Děkuji.

Profilový obrázek
posjirka
19.6.2016 at 11:03

Zbyšku …. tleskám. Takhle hezky vysvětlení tříd a metod jsem nikde jinde neviděl.
Fakt super.

Zbyšek Voda
Zbyšek Voda
20.6.2016 at 15:06

Děkuji. To bylo cílem, tak jsem rád, že se mi to snad i povedlo :)

Profilový obrázek
Tomáš
19.6.2016 at 10:48

Napsat komentář

shares