Lekce 12: Třídy I
- Touto lekcí začíná lehce pokročilé programování v PHP.
- Jako první lekci si představíme třídy, které patří do objektově orientovaného programování - OOP.
- Objekt je něco, co dokáže udržovat svůj stav a interagovat s okolím zasíláním a přijímáním zpráv.
- OOP vzniklo jako reakce na stále se zvyšující složitost programů s cílem usnadnit jejich psaní.
- V dnešní době je OOP běžná záležitost a je to nutné znát - aspoň základy. Hlavně u větších programů je to nezbytné.
Tvorba tříd
- Název třídy je opakem názvu všeho ostatního, protože název třídy začíná vždy velkým písmenem.
- Deklarace třídy je dělá pomocí klíčového slova class.
class Auto
{
// nejaky obsah tridy
}
- Název je většinou jedno slovo. Pokud slov je více, tak se spojí jako u funkcí.. například
MaleAuto,
MojeSuperTrida apod.
Pozor: Za názem třídy nikdy nejsou kulaté závorky jako u funkcí, takže neplést!
- Jakmile máme vytvořenou třídu Auto, tak do ní můžeme vkládat funkce a proměnné.
- Než ale začnem, tak je důležité zmínit
modifikátory přístupu, které je nutné znát a používat.
public - veřejný člen... je přístupný uvnitř i mimo třídu (vychozí)
protected - chráněný člen... je přístupný pouze uvnitř třídy a třídách odvozených z této třídy
private - soukromý člen... je přístupný pouze uvnitř třídy
- Tyto modifikátory si dobře zapamatujte, protože používat třídu bez nich je jako nepoužívat třídu vůbec.
- No a jakmile známe modifikátory, tak si můžeme ukázat daklaraci proměnných do třídy.
class Auto
{
// deklarace 2 privatnich promennych, ktere je mozne pouzit pouze ve tride
private $rychlost;
private $hmotnost;
}
- Deklarace proměnných nemusí mít nutně hodnotu, výchozí hodnota je
null.
- Pokud máme takovýto tvar, kde jsou 2 a více proměnných bez hodnoty se stejným modifikátorem, tak to lze zapsat i jako:
class Auto
{
private $rychlost, $hmotnost;
}
- Tento způsob se ale moc nedoporučuje, hlavně z pohledu přehlednosti. My budeme používat ten první - co proměnná, to nový řádek.
- Jako další věc bych vám představil
gettry a
settry. Ty slouží k tomu, aby jsme mohli přistupovat k privátním proměnným mimo třídu (přes objekt) a
jak už název říká, tak
gettry slouží pro získání hodnoty a
settry pro její nastavení.
- Ale nebojte, není to nic jiného, než obyčejná funkce. Jediný rozdíl bude v jejím jménu. Pro getry se přidá do názvu
get a pro setry
set a hlavně funkce
musí být
public.
class Auto
{
private $rychlost, $hmotnost;
// gettry - ziska pouze hodnotu promennych
public function getRychlost() { return $this->rychlost; }
public function getHmotnost() { return $this->hmotnost; }
// settry - nastavuje hodnotu promennych
public function setRychlost($rychlost) { $this->rychlost = $rychlost; }
public function setHmotnost($hmotnost) { $this->hmotnost = $hmotnost; }
}
- Určitě jste si všimli, že v každé funkci používám místo normálního názvu proměnné, tvar
$this->promenna.
- Toto slovíčko
$this slouží k tomu, aby jsme mohli přistupovat k proměnným, které jsou ve třídě (bez vyjjímky modifikátoru).
Zároveň nám odlišuje proměnné uvnitř tříd a lokální ve funkcích.
- Teď vás asi bude zajímat, jak vůbec můžu třídu použít, když jí mám takto vytvořenou.
- Jak jsem předtím řekl, tak třída je objekt, takže máme nový datový typ a to
object. A objekty tvoříme pomocí slovíčka
new.
$prom = new Auto(); // vytvorime objekt Auto na promenne $prom
$prom = new Auto; // v tomto pripade lze zapsat i takto
$prom->setRychlost(120); // nastavime rychlost auta
$prom->setHmotnost(1650); // nastavime hmotnost auta
// vypisem: "Auto jede rychlostí 120 km/h a váží 1650 kg."
echo "Auto jede rychlostí ".$prom->getRychlost()." km/h a váží ".$prom->getHmotnost()." kg.";
- Jednoduše řečeno... proměnná, na které se vytvoří třída bude typu objekt a pomocí šipky
-> se volají funkce nebo proměnné, které jsou ve třídě
public.
- V dalším příkladu uvedu funkci, která je pouze ve třídě a trochu si zkusíme modifikátory.
class Funkce // jmeno tridy
{
// pokud nezadam modifikator "public", tak funkce bude stale "public"
// doporucuji vsak modifikator vzdy uvadet, at je to jasne videt
public function vypis1($text) { echo $text; }
protected function vypis2($text) { echo $text; } // protected
private function vypis3($text) { echo $text; } // private
function vypis4($text) { echo $text; } // bez modifikatoru
}
$fce = new Funkce();
$fce->vypis1("Bagr"); // funguje
$fce->vypis2("Bagr"); // fatal error
$fce->vypis3("Bagr"); // fatal error
$fce->vypis4("Bagr"); // funguje
- Nyní bych chtěl ještě zmínit nový příkaz
instanceof, který porovnává objekty a vrací true nebo false.
- Je proto užitečný v porovnání tříd, jestli daný objekt náleží té třídě nebo ne.
class A { } // nejaka trida A
class B { } // nejaka trida B
$a = new A(); // vytvorime objekt trida A
if ($a instanceof A) // porovname, jestli $a patri k A
{
echo "Proměnná náleží třídě A"; // vypise toto
}
else echo "Proměnná NEnáleží třídě B";
- Jako příklad použití může být případ, kde budeme mít nějaké pole objektů dvou nebo více tříd a díky
instanceof můžeme rozlišit,
k jaké třídě objekt patří.
- Nastala by kritická chyba, kdyby jsme volali třeba funkci třídy A, která v ní neexistuje, ale je ve třídě B.
class A
{
// trida A ma funkci pro vypsani cisla
public function vypisCislo() { return 10; }
}
class B
{
// trida B ma funkci pro vypsani jmena
public function vypisJmeno() { return "Pavel"; }
}
// do pole si ulozime 2 objekty (tridu A i B)
$pole = array(new A(), new B());
foreach ($pole as $p) // projdeme pole
{
// SPATNY zpusob !!
echo $p->vypisJmeno(); // fatal error
echo $p->vypisCislo(); // fatal error
// SPRAVNY zpusob
// musime zjistit, k jakemu objektu dana funkce patri
if ($p instanceof A)
{
echo $p->vypisCislo();
}
else echo $p->vypisJmeno();
}
Konstruktory a destruktory
- Konstruktor je výborná věc. Je to vlastně funkce, která má specifický název a volá se automaticky po vytvoření objektu třídy.
- Jméno funkce pro konstruktor je __construct() a nemá žádný návratový typ a musí být vždy public.
- Uvedem si příklad, jak pomocí konstruktoru vypíši text.
class Text
{
public function __construct($text)
{
echo $text;
}
}
- Volání a použití třídy bude tedy:
$text = new Text("bagr"); // vypise "bagr"
new Text("bagr"); // to same
- Konstruktor může volat cokoliv, i vaše funkce uvnitř třídy. Může sloužit jako nastavení prvotních hodnot.
class Text
{
private $text;
public function __construct()
{
$this->text = "Zde zatím žádný text není!";
}
public function nastavText($text) { $this->text = $text; }
public function vypisText() { echo $this->text; }
}
$texty = new Text();
$texty->vypisText(); // vypise "Zde zatím žádný text není!"
$texty->nastavText("bagr");
$texty->vypisText(); // vypise "bagr"
- Ještě bych chtěl dodat, že konstruktory by se měli uvádět jako první funkce ve třídě.
- Destruktor je opakem konstruktoru a deklaruje se jako poslední funkce ve třídě a nese název
__destruct().
- Destruktor stejně jako konstruktor nemá žádný návratový typ a volá se automaticky, až jako poslední.
class Trida
{
public function __destruct() { echo "bagr"; }
}
new Trida(); // vypise "bagr"
- Je ve všem stejný jako konstruktor, až na jednu věc... destruktor
nemá žádné parametry.
- Můžeme konstruktor i destruktor použít na automatické vygenerování html hlaviček a patiček. Možnosti jsou široké.
class Web
{
// konstruktor, pro vytvoreni hlavicky
public function __construct()
{
echo '<head> ... </head><body>';
}
// text, ktery se napise do tela webu
public function text($vstup) { echo $vstup; }
// destruktor, pro vytvoreni paticky
public function __destruct()
{
echo '<div id="footer"> ... </div></body>';
}
}
$web = new Web(); // vytvori objekt a vypise konstruktor (hlavicku webu)
$web->text("bagr"); // do tela vypise text a hned za to se prida destruktor (paticka)
// vypise: <head> ... </head><body>bagr<div id="footer"> ... </div></body>
Třída a konstanty
- V příkazech jsem se naučili příkaz const, tak ho nyní můžeme využít.
- Jen pro připomenutí.. konstanta je hodnota, která slouží pouze pro čtení a píše se velkými písmeny.
- Určitě víte, jak se volají konstanty normálně. Ve třídách je to trochu jiné.
- Konstanta je vždy public a volat jí můžeme hned několika způsoby.
- Ukážeme si, jak se konstanta volá ve třídě.
class Dynamit
{
const POCET = 10;
public function vypis()
{
echo "Máme ".POCET." kusů dynamitu."; // chyba
echo "Máme ".self::POCET." kusů dynamitu."; // spravne (bezny zpusob)
echo "Máme ".Dynamit::POCET." kusů dynamitu."; // spravne
echo "Máme ".static::POCET." kusů dynamitu."; // spravne (moc se nepouziva)
}
}
- Doporučuji používat volání konstanty přes
self, to znamená, že volá současnou třídu, ve které se konstanta nachází a
pomocí
:: (znáte možná z C/C++) se přidělí její název.
- Třetí možnost volá přes název třídy, také to není chyba. Je to naprosto to samé, jako předchozí
self.
- Poslední možnost přes
static je spíše určeno pro statické deklarace, ale konstanta je též statická - proto to lze použít.
Jinak
static si ukážeme trochu níže.
- Volání konstanty mimo třídu je jednoduché, k tomu použijeme třetí způsob - více způsobů ani neni.
- Výhodou je, že nemusíme tvořit objekt... můžeme hned volat.
echo Dynamit::POCET; // vypise 10
- Pokud dáme konstantu mimo funkci, tak se chová stejně tak, jak ji známe.
const NOVY_POCET = 50; // konstanta mimo tridu
class Dynamit
{
public function vypis()
{
echo "Máme ".NOVY_POCET." kusů dynamitu."; // spravne
}
}
- Trochu jiné to bude pro zjištění existence konstanty.
- K tomu použijeme funkci
defined(), kterou již známe, ale tvar bude trochu odlišný.
class Hodnoty
{
const VAL = 50;
public function __construct()
{
// toto by jsme logicky mohli pouzit, ale je to CHYBA!
if (defined(self::VAL)) echo "Existuje";
// spravny zpusob pro tridu
if (defined(__CLASS__.'::'.VAL)) echo "Existuje";
}
}
- U zjištění existence konstanty ve třídě je nutné uvést název třídy a ::, takže lze to zapsat i jako
Hodnoty::VAL.
- My jsme použili příkaz
__CLASS__, protože vrací název třídy (je to více dynamické). Pokud by jsme změnili název třídy,
tak se nemusíme starat o změny v kódu a to jen, kvůli názvu třídy.
- Teď si představíme typ
static, který je tak trochu zvláštní, protože aby jsme se dostali ke statickým členům, tak nemusíme tvořit objekt,
ale lze k nim přistupovat přímo pomocí
::.
- Volání statického členu mimo funkci je stejné jako u konstanty, ale lze to pouze u modifikátoru
public.
- Pokud statický člen voláme uvnitř třídy, tak je to stejné jako u konstanty -
self nebo zde i
static.
- Stručně řečeno... statický člen je proměnná, u které lze měnit hodnoty a přidávat modifikátory, ale ve všem ostatním se chová jako konstanta.
class Dynamit
{
public static $cislo = 10; // verejna
private static $moje = 50; // privatni - pouze pro tuto tridu
public function vypis()
{
echo "Máme ".self::$cislo." kusů dynamitu.";
}
}
echo Dynamit::$cislo; // vypise 10
echo Dynamit::$moje; // fatal error - privatni clen
- Samozřejmě statická nemusí být pouze proměnná, ale můžeme udělat i statickou funkci... zde ale platí určitá pravidla.
class Bagr
{
private $cislo = 10; // bezna promenna vazana s objektem tridy
private static $CISLO = 20; // staticka promenna
// v poradku, ne-staticka funkce muze pouzivat jak objekty, tak staticke cleny
public function vypis()
{
echo $this->cislo;
echo self::$CISLO;
}
// chyba, staticka funkce obsahuje volani ne-staticke promenne (pres $this)
public static function napis()
{
echo $this->cislo; // chyba - potrebuje objekt
echo self::$CISLO;
}
// v poradku, staticka funkce vola staticke promenne
public static function zapis()
{
echo self::$CISLO;
}
}
$obj = new Bagr();
$obj->vypis(); // v poradku
$obj->napis(); // fatal error - nelze volat statickou funkci pres objekt
Bagr::napis(); // fatal error - funkce obsahuje volani ne-staticke promenne
Bagr::zapis(); // v poradku
- Pokud vás napadne, že slovíčko
static nacpete do konstruktoru nebo destruktoru, tak to vás musím sklamat.
Konstruktory i destruktory jsou vázaný na objekty, zatím co statické členy ne.
- Můžeme si ještě ke konci ukázat plně statickou třídu.
class Bagr
{
private static $num; // staticka promenna
public static function init() // bude nahrazovat konstruktor
{
self::$num = 5; // nastavi hodnotu
}
public static function nastav($num) { self::$num = $num; } // nastavi hodnotu
public static function vypis() { echo self::$num; } // vypise hodnotu
}
Bagr::vypis(); // zde nevypise nic, hodnota ma NULL
Bagr::init(); // nastavi hodnotu na 5
Bagr::vypis(); // vypise 5
Bagr::nastav(10); // nastavime 10
Bagr::vypis(); // vypiseme 10
Dědění
- Dědičnost je celkem silná zbraň OOP, protože dokáže rozšiřovat objekty, takže se objekt neváže pouze na jednu třídu, ale na několik.
- Je to stejné jako ve skutečném světě - děti dědí z rodiče a ty zase z prarodiče. Je to taková struktůra stromu.
- Vytvořme si příklad, kde budeme mít hlavní třídu Zvire, kde budou nějaké vlastnosti zvířat, které mají všichni stejné.
Dále budeme mít dvě další třídy Pes a Kocka. Tyto dvě třídy budou dědit z hlavní třídy Zvire a nejenom,
že dědí všechny vlastnosti předchozí třídy, ale přidají se nové, které mají pouze ta 2 zvířata.
- Pojďme si tedy ukázat příklad v praxi.
// hlavni abstraktni trida Zvire
abstract class Zvire
{
// prvky tridy
private $vek;
private $hmotnost;
// konstruktor pro nastaveni veku a hmotnosti
public function __construct($vek, $hmotnost)
{
$this->vek = $vek;
$this->hmotnost = $hmotnost;
}
// gettry pro prvky tridy
public function getVek() { return $this->vek; }
public function getHmotnost() { return $this->hmotnost; }
}
// finalni trida Pes, ktera dedi ze Zvire
final class Pes extends Zvire
{
private $umiStekat; // privatni promenna pro pocet zivotu
// konstruktor tridy Kocka, do ktereho se vkladaji prvky ze trid, od kterych dedi a
// zaroven prvky teto tridy
public function __construct($vek, $hmotnost, $umiStekat)
{
parent::__construct($vek, $hmotnost); // dedeny konstruktor
$this->umiStekat = $umiStekat;
}
// getter pro ziskani jestli pes umi stekat
public function getUmiStekat() { return $this->umiStekat; }
}
// finalni trida Kocka, ktera dedi ze Zvire
final class Kocka extends Zvire
{
private $pocetZivotu; // privatni promenna pro pocet zivotu
// konstruktor tridy Kocka, do ktereho se vkladaji prvky ze trid, od kterych dedi a
// zaroven prvky teto tridy
public function __construct($vek, $hmotnost, $pocetZivotu)
{
parent::__construct($vek, $hmotnost); // dedeny konstruktor
$this->pocetZivotu = $pocetZivotu;
}
// getter pro ziskani poctu zivotu
public function getPocetZivotu() { return $this->pocetZivotu; }
}
$pes1 = new Pes(5, 10, true); // pes1 = 5 let, 10kg a umi stekat
$pes2 = new Pes(8, 12, false); // pes2 = 8 let, 12kg a neumi stekat
$kocka1 = new Kocka(2, 3, 7); // kocka1 = 2 roky, 3kg a ma stale 7 zivotu
$kocka2 = new Kocka(4, 5, 4); // kocka2 = 4 roky, 5kg a ma jen 4 zivoty
- Je to celkem přehledně okomentovaný, takže bych se zaměřil na věci, které zatím neznáme a proč to tak je.
- Začnu asi příkazem
extends, tento příkaz ukazuje na třídu, ze které se má dědit.
- První co je nové, jsou modifikátory
abstract a
final, které se používají pro třídu.
-
Abstract vlastně znamená, že třídu nemůžeme použít jako objekt (nelze z ní vytvořit objekt pomocí
new).
Je to vlastně takové zabezpečení, aby k ní mohl být přístup pouze ze tříd, které jí dědí.
- Tady se dostáváme k pravidlu, že třída, která dědí z nejvíce tříd, je nejschopnější - může toho nejvíc.
- Druhým modifikátorem je
final. Jak už název říká, tak se bude jednat o finální třídu, to znamená, že jí už nelze dále dědit.
- Další, co je zde nové, je příkaz
parent. Tento příkaz volá konstruktor předka a přes současnou třídu se nastaví i třída děděná (právě přes ten konstruktor).
- Pomocí veřejných funkcí (gettrů), které jsou jak v hlavní třídě, tak děděných... můžeme volat hodnoty proměnných, protože se dědí také.
Pozor: Dědit pomocí
extends můžeme pouze z jedné třídy!
- Zkusíme to u menších příkladů. První příklad jsem možná trochu přehnal.
class Hlavni // hlavni trida
{
// objektove promenne
private $A = 10;
protected $B = 20;
public $C = 30;
// staticke promenne
private static $D = 40;
protected static $E = 50;
public static $F = 60;
}
class Vedlejsi extends hlavni // vedlejsi trida co dedi z Hlavni
{
public function __construct()
{
echo $A; // chyba - jedna se o lokalni promennou
echo parent::$A; // fatal error - promenna ve tride Hlavni je private
echo parent::$B; // fatal error - pristup je mozny, ale promenna neni static
echo parent::$C; // fatal error - to sami jako u $B
echo parent::$D; // fatal error - pristup je mozny, promenna je private
echo parent::$E; // v poradku, vypise 50
echo parent::$F; // v poradku, vypise 60
echo parent::$this->A; // notice - promenna neexistuje (je private)
echo parent::$this->B; // v poradku, vypise 20
echo parent::$this->C; // v poradku, vypise 30
echo parent::$this->D; // notice - promenna neexistuje (je private)
echo parent::$this->E; // strict - promenna je staticka
echo parent::$this->F; // notice - to same jako u $E
echo $this->A; // notice - nedefinovana promenna
echo $this->B; // v poradku, vypise 20
echo $this->C; // v poradku, vypise 30
echo $this->D; // notice - nedefinovana promenna
echo $this->E; // strict - nelze takto pristupovat ke staticke promenne
echo $this->F; // notice - to same jako u $E
}
}
new Vedlejsi(); // vytvoreni objektu vedlejsi tridy (pro volani konstruktoru)
- Zde vidíte jak lze přistupovat k proměnným, které se dědí a jak nelze.
- Slovíčko
parent, které jsem sice vysvětlil, ale jen připomenu... ukazuje na rodiče - třídu děděnou.
// mame tyto tridy
class Hlavni { } // Hlavni trida
class Vedlejsi extends hlavni { } // Vedlejsi trida, ktera dedi z Hlavni
class Dalsi extends Vedlejsi { } // Dalsi trida, ktera dedi z Vedlejsi
// vytvareni objektu trid
new Hlavni(); // objekt hlavni tridy bude obsahovat jen sam sebe
new Vedlejsi(); // bude obsahovat tridu Hlavni a sam sebe
new Dalsi(); // bude obsahovat tridy Hlavni, Vedlejsi a sam sebe
- Zde je opět vidět, jak poslední třída
Dalsi obsahuje nejvíce informací a možností než předchozí 2 třídy.
- Teď si ukážem modifikátory
abstract a
final.
// mame tyto tridy
abstract class Hlavni { } // Hlavni abstraktni trida
class Vedlejsi extends hlavni { } // Vedlejsi trida, ktera dedi z Hlavni
final class Dalsi extends hlavni { } // Dalsi trida, ktera dedi z Hlavni
new Hlavni(); // fatal error - nelze vytvorit objekt abstraktni tridy
new Vedlejsi(); // v poradku
new Dalsi(); // v poradku
// opet mame tyto tridy
final class Hlavni { } // Hlavni finalni trida
class Vedlejsi extends hlavni { } // Vedlejsi trida, ktera dedi z Hlavni
final class Dalsi extends hlavni { } // Dalsi trida, ktera dedi z Hlavni
new Hlavni(); // v poradku
new Vedlejsi(); // fatal error - nelze dedit z finalni tridy
new Dalsi(); // fatal error - nelze dedit z finalni tridy
- Ovšem modifikátor
final se nemusí týkat pouze tříd, ale je možné ho aplikovat i na funkce.
- U funkcí má trochu jiný význam a to, že zamezuje překrývání funkcí.
- Uvedem si tedy příklad, jak vypadá překrývání funkce a poté jak to vypadá po aplikování modifikátoru
final.
class A
{
// pokud by jsme zde vytvorili objekt na tridu A a zavolali funkci vypis(),
// tak se vypise slovo "ahoj"
public function vypis() { echo "ahoj"; }
}
class B extends A
{
// v tomhle pripade, pokud vytvorime objekt na tridu B, ktera dedi od A a zavolali
// funkci vypis(), tak se prekryje puvodni funkce ve tride A a vypise "svete"
public function vypis() { echo "svete"; }
}
- Z této ukázky je to celkem jasné - novější funkce vždy přepisují starší, my však můžeme zařídit, aby to nešlo a to pomocí modifikátoru
final.
class A
{
// opet stejny vysledek jako predtim
final public function vypis() { echo "ahoj"; }
}
class B extends A
{
// zde jiz nastava fatal error, protoze finalni funkce se neda prekryt / prepsat
public function vypis() { echo "svete"; }
}
Dobrovolný domácí úkol
1) Vytvořte třídu Matice, kde budou funkce vytvor(velikost_matice, minCislo, maxCislo), vynulujDiagonaly() a vypis().
Kde do vytvor(...) se zadá velikost matice třeba 6 = 6x6 a min a max čísla (od 1 do 9), která se budou do matice náhodně generovat v tom rozmezí.
Funkce vynulujDiagonaly() je jasná, po vygenerování matice se zavolá tato funkce a nastaví na hlavní i vedlejší diagonále samé 0.
A poslední funkce vypis() matici vypíše - musí mít tvar matice.
- Výstup by měl vypadat nějak takto pro matici 6x6 - čísla jsou náhodná.
0 5 4 3 4 0
2 0 6 6 0 7
4 7 0 0 6 2
1 9 0 0 5 5
9 0 3 5 0 4
0 6 5 8 9 0
class Matice
{
private $pole; // uchovava matici - pouze pro tridu
private $velikost; // uchovava velikost matice - opet pouze pro tridu
// vytvori matici
public function vytvorPole($velikost, $min, $max)
{
$this->velikost = $velikost; // nastavime velikost do promenne tridy
for ($i = 0; $i < $velikost; $i++)
{
for ($j = 0; $j < $velikost; $j++)
{
$this->pole[$i][$j] = rand($min, $max); // generuje cisla do matice
}
}
}
// funkce pro vynulovani hlavni a vedlejsi diagonaly
public function vynulujDiagonaly()
{
for ($i = 0; $i < $this->velikost; $i++)
{
$this->pole[$i][$i] = 0; // hlavni
$this->pole[$this->velikost - $i - 1][$i] = 0; // vedlejsi
}
}
// vypisuje matici
public function vypis()
{
for ($i = 0; $i < $this->velikost; $i++)
{
for ($j = 0; $j < $this->velikost; $j++)
{
echo $this->pole[$i][$j]."\t"; // odsadi tabulatorem
}
echo '
'; // novy radek
}
}
}
$mat = new Matice(); // novy objekt matice
// vytvori matici s velikosti 6x6 s nahodnymi cisly od 1 do 9
$mat->vytvorPole(6, 1, 9);
$mat->vynulujDiagonaly(); // vynuluje diagonaly
$mat->vypis(); // vypise matici
2) Vytvořte třídu
Auto, která bude obsahovat informace o automobilu - znacku, max. rychlost, hmotnost a cenu.
Přes konstruktor zadáme všechny informace - tím vytvoříme nové auto. Nyní si mimo třídu vytvoříme pole, do kterého vložíme 3 objekty aut.
Poté přes cyklus je vypíšem - informace o každém automobilu.
- Výpis z pole by měl vypadat třeba takto.
Značka: Škoda
Maximální rychlost: 200 km/h
Hmotnost: 1650 kg
Cena: 350000 kč
Značka: Ford
Maximální rychlost: 240 km/h
Hmotnost: 1422 kg
Cena: 498000 kč
Značka: Fiat
Maximální rychlost: 180 km/h
Hmotnost: 1210 kg
Cena: 280000 kč
class Auto
{
// uchovava informace o aute
private $znacka;
private $maxrychlost;
private $hmotnost;
private $cena;
// pres konstruktor vytvori auto
public function __construct($znacka, $maxrychlost, $hmotnost, $cena)
{
$this->znacka = $znacka;
$this->maxrychlost = $maxrychlost;
$this->hmotnost = $hmotnost;
$this->cena = $cena;
}
// pouze gettry pro ziskani informaci z privatnich promennych
public function getZnacka() { return $this->znacka; }
public function getMaxRychlost() { return $this->maxrychlost; }
public function getHmotnost() { return $this->hmotnost; }
public function getCena() { return $this->cena; }
}
// nase pole aut (objektu)
$poleAut = array(
new Auto("Škoda", 200, 1650, 350000),
new Auto("Ford", 240, 1422, 498000),
new Auto("Fiat", 180, 1210, 280000)
);
// cyklus pro vypsani informaci o kazdem aute
foreach ($poleAut as $row)
{
echo "Značka: ".$row->getZnacka()."
";
echo "Maximální rychlost: ".$row->getMaxRychlost()." km/h
";
echo "Hmotnost: ".$row->getHmotnost()." kg
";
echo "Cena: ".$row->getCena()." kč
";
}
//PS: promenna $row ukazuje na objekt tridy Auto, proto je mozne takto pristupovat
3) Vytvořte třídu
Stroje, která bude obsahovat prázdné pole a dvě funkce
pridejProstredek(objekt), přes který se budou přidávat prostředky do pole (celé třídy).
Druhá funkce bude
vypisProstredky(), která vypíše celé pole se všemi vlastnostmi, které ten objekt má.
Poté si vytvořte třídu
DopravniProstredky a ta bude obsahovat 4 základní vlastnosti, který každý prostředek bude mít a to
typ,
hmotnost,
rychlost a
barva.
Na konec vytvoříme třídu
Auto s vlastností
rodinnyVuz a třídu
Autobus s vlastností
pocetMist.
Nyní do pole přidáme 2 objekty Auta a Autobusu a vypíšem. Ještě bych chtěl doplnit, že
rodinnyVuz je typ bool a až ve výpisu se mění na string (ano/ne).
Dále nezapomeňte uvést, jestli daný objekt je Auto nebo Autobus a na konec počet objektů v poli.
- Takto by měl vypadat výpis.
Stroj: Auto
Typ: Ford
Hmotnost: 1866 kg
Rychlost: 260 km/h
Barva: Černá
Rodinné auto: ano
Stroj: Auto
Typ: Mazda
Hmotnost: 1610 kg
Rychlost: 280 km/h
Barva: Červená
Rodinné auto: ne
Stroj: Autobus
Typ: Ikarus
Hmotnost: 2680 kg
Rychlost: 180 km/h
Barva: Bílá
Počet míst: 46
Stroj: Autobus
Typ: Scania
Hmotnost: 2976 kg
Rychlost: 220 km/h
Barva: Modrá
Počet míst: 58
Počet strojů: 4
final class Stroje // finalni trida stroje
{
private $pole; // zde bude prazdne pole
// pridava objekty do pole (dopravni prostredky)
public function pridejProstredek($obj)
{
$this->pole[] = $obj;
}
// vypisuje cele pole
public function vypisProstredky()
{
$out = null;
foreach ($this->pole as $row)
{
// pomoci instanceof zjistuje, zda se jedna o Auto nebo Autobus
$out.= "Stroj: ".(($row instanceof Auto) ? "Auto" : "Autobus")."
";
$out.= "Typ: ".$row->getTyp()."
";
$out.= "Hmotnost: ".$row->getHmotnost()." kg
";
$out.= "Rychlost: ".$row->getRychlost()." km/h
";
$out.= "Barva: ".$row->getBarva()."
";
// kontroluje typ objektu, aby nesahl po funkci, ktera v objektu neexistuje
if ($row instanceof Auto)
{
$rod = ($row->getRodinnyVuz()) ? "ano" : "ne";
$out.= "Rodinné auto: ".$rod."
";
}
else $out.= "Počet míst: ".$row->getPocetMist()."
";
$out.= "
";
}
echo $out;
echo "Počet strojů: ".count($this->pole); // velikost pole
}
}
abstract class DopravniProstredky // abstraktni trida pro dopravni prostredky
{
// sdilene vlastnosti
private $typ;
private $hmotnost;
private $rychlost;
private $barva;
// pres konstruktor se nastavi vlastnosti objektu
public function __construct($typ, $hmotnost, $rychlost, $barva)
{
$this->typ = $typ;
$this->hmotnost = $hmotnost;
$this->rychlost = $rychlost;
$this->barva = $barva;
}
// gettry pro ziskani hodnoty z privatni promenne
public function getTyp() { return $this->typ; }
public function getHmotnost() { return $this->hmotnost; }
public function getRychlost() { return $this->rychlost; }
public function getBarva() { return $this->barva; }
}
// finalni trida Auto, co dedi prostredky
final class Auto extends DopravniProstredky
{
private $rodinnyVuz; // vlastnost auta
// pres konstruktor se nastavi vlastnost automobilu
public function __construct($typ, $hmotnost, $rychlost, $barva, $rodinnyVuz)
{
// pristupuje k dedene tride a nastavuje jeji vlastnosti pres tuto tridu
parent::__construct($typ, $hmotnost, $rychlost, $barva);
$this->rodinnyVuz = $rodinnyVuz;
}
// getter pro ziskani hodnoty z privatni promenny
public function getRodinnyVuz() { return $this->rodinnyVuz; }
}
// finalni trida Autobus, ktera dedi z prostredku
final class Autobus extends DopravniProstredky
{
private $pocetMist; // vlastnost autobusu
// pres konstruktor se nastavi vlastnost autobusu
public function __construct($typ, $hmotnost, $rychlost, $barva, $pocetMist)
{
// pristupuje k dedene tride a nastavuje jeji vlastnosti pres tuto tridu
parent::__construct($typ, $hmotnost, $rychlost, $barva);
$this->pocetMist = $pocetMist;
}
// getter pro ziskani hodnoty z privatni promenny
public function getPocetMist() { return $this->pocetMist; }
}
$stroj = new Stroje(); // vytvorime objekt tridy Stroje
// pridame tyto objekty do pole
$stroj->pridejProstredek(new Auto("Ford", 1866, 260, "Černá", true));
$stroj->pridejProstredek(new Auto("Mazda", 1610, 280, "Červená", false));
$stroj->pridejProstredek(new Autobus("Ikarus", 2680, 180, "Bílá", 46));
$stroj->pridejProstredek(new Autobus("Scania", 2976, 220, "Modrá", 58));
$stroj->vypisProstredky(); // vypisem pole