Objektově orientované programování (OOP)
ZÁKLADNÍ PRINCIPY OOP
Celé objektově orientované programování stojí na 4 principech:
- zapouzdření - umožní skrýt některé atributy a některé metody. Ty jsou přístupné přes "rozhraní", které umožní s nimi pracovat.
- dědičnost - umožní vytvářet třídy, které dědí vlastnosti svých "rodičů", tedy nadřazených tříd.
- polymorfismus - umožní definovat metody se stejnou hlavičkou pro instance různých tříd. Přizpůsobíme tedy funkčnost metody podle třídy - ve spojení s dědičností jde o silný nástroj.
- abstrakce - použití tříd a objektů (instancí třídy)
DEFINICE TŘÍDY
Základem OOP je práce s objekty. Objekt je odlišitelný od ostatních objektů a má nějaké vlastnosti a schopnosti. Objektem může být auto, strom, zaměstnanec, okno nebo tlačítko v operačním systému. Uživatel objektu přistupuje k jednotlivým objektům jako k "černým skříňkám". Nezajímá se, jakým způsobem objekty služby poskytují, ale zajímá se jen, jaké služby poskytují a jak je může použít.
Obecným popisem pro objekty stejné skupiny je třída. Třída je vlastně předpisem, jak vytvořit objekt.Jednotlivé objekty každé třídy nazýváme instance třídy.
class NazevTridy [: předchůdci třídy] //předchůdce určujeme v případě dědičnosti
{
// Položky třídy
};
Jedním ze základních pilířů OOP je tzv. zapouzdření, tedy uchovávat si atributy třídy pro sebe a ven vystavovat jen metody. K tomu použijeme nastavení public a private.
Ve třídě definujeme její položky t.j. datové prvky (atributy, členské proměnné) a metody (členské funkce). Položky mohou být:
- soukromé (private), např. atributy třidy, ke kterým mají přístup jen metody dané třídy
- veřejné (public), přístupné v programu, vytvářejí rozhraní pro praci s objektem
- chráněné (protected), přístupné v dané třídě a třídách odvozených
Je dobrým zvykem nastavit všechna data (atributy třídy) jako soukromé a vytvořit k nim přístupové veřejné metody (pro získání nebo nastavení hodnoty - tzv. getter a setter). K soukromým položkám se totiž dostaneme přímo ve všech metodách dané třídy, ale "zvenku" se k nim dostaneme jenom použitím odpovídající metody.
// příklad definice třídy
class Vozidlo
{
private:
string Spz;
int RokVyroby;
public:
//přístupové metody - typu set (nastav) a get (dej)
bool NastavSpz(const string s); //nastaví (změní) SPZ
void NastavRokVyroby(int rv); //nastaví (změní) rok výroby
string DejSpz() const; //vrátí SPZ, nemění atributy třídy
int DejRokVyroby() const; //vrátí rok výroby, nemění atributy třídy
};
Při definici třídy jsme uvedli jenom hlavičky metod, je potřebné metody ještě definovat (uvést jejich kompletní kód). Je možné je definovat přímo ve třídě (inline), ale u složitějších tříd je potom zápis nepřehledný. Inline definice metod je vhodné použít u jednoduchých metod. Dále je uveden příklad definice metody mimo třídu. Operátor :: označuje příslušnost metody ke třídě.
bool Vozidlo::NastavSpz(const string s)
{
if(s.length()>8) return false; //jednoduché ošetření pro SPZ
this->Spz = s;
return true;
}
void Vozidlo::NastavRokVyroby(int rv)
{
this->RokVyroby = rv;
}
string Vozidlo::DejSpz() const
{
return this->Spz;
}
int Vozidlo::DejRokVyroby() const
{
return this->RokVyroby;
}
V případě vytváření projektu bude definice třídy v hlavičkovém souboru a definice členských funkcí dáme do odpovídajícího zdrojového kódu.
Instance (objekty) pro jednotlivé třídy vytváříme podobně jako "proměnnou pro danou třídu". K jednotlivým položkám přistupujeme přes operátor tečka (u statických instancí) nebo přes operátor -> (v případě ukazatelů). Soukromé položky nejsou přístupné přímo, jenom přes metody.
int main()
{
Vozidlo prvni, druhe;
string spz;
cout << "Prvni auto: " ;
prvni.NastavSpz("1T2 3333");
cout << prvni.DejSpz() << endl;
cout << "Druhe auto: " ;
cout << "Zadejte SPZ: " ;
getline(cin,spz);
if(druhe.NastavSpz(spz)) //s vyuzitim osetreni SPZ
{
cout << druhe.DejSpz() << endl;
}
else
{
cout << "spatna SPZ " << endl;
}
return 0;
}
Postupně přidáváme do definice třídy další potřebné metody např. pro výpis informací o vozidle. K datovým položkám můžeme přistupovat přímo, protože se jedná o členskou funkci stejné třídy.
void Vozidlo::VypisVozidlo() const
{
cout << "Informace o vozidle:" << this->Spz << ", " << this->RokVyroby << endl;
}
// použití metody pro proměnnou prvni z předchozího příkladu:
// prvni.VypisVozidlo();