Učíme se PHP online a nekupujem knihy :o)

>> Pro všechny, kdo mají rádi tento jazyk nebo pro ty, kteří se v něm chějí zdokonalit.



Lekce 15: Rozhraní




- Tato lekce trochu navazuje na třídy, protože nikde jinde se rozhraní nepoužívá.
- K čemu vůbec je? Slouží hlavně pro zpřehlednění kódu a kvůli bezpečnosti.
- Pokud do nějaké třídy naimplementujeme rozhraní, tak ta třída musí obsahovat funkce, které to rozhraní má.


Jak používat rozhraní


- Nejprve si řekneme, co můžeme a nemůžeme používat
- Jedna třída může implementovat více, než jedno rozhraní (oddělují se čárkou).
- Pokud třída bude implementuje více, než jedno rozhraní, tak funkce v každém rozhraní musí být odlišné.
- Třída musí obsahovat stejné funkce, které jsou definovány v rozhraní, jinak vypíše fatal error.
- Je tradicí, že rozhraní začíná písmenem "i" nebo "I", aby bylo jasně vidět, že se jedná o rozhraní.
- Rozhraní může obsahovat konstanty a všechny definice musí být v rozhraní veřejné nebo statické.
- Nyní si ukážem, jak se vytvoří takové základní rozhraní.

interface iPotrebne
{
  const POCET = 10; // nejaka konstanta v rozhrani
}
- Rozhraní se vytvoří příkazem interface.
- Správně by jméno mělo začínat vždy velkým písmenem, ale budu používat malé "i", protože mi to tak vyhovuje.

- Použít rozhraní třeba na seznam konstant je také možné, ale né moc běžné. Volání pak vypadá stejně, jako u tříd.
echo iPotrebne::POCET; // vypise 10
- Ukážem si spíše hlavní využití rozhraní a to ve spojení se třídami.
- Už víme, že dědění je pomocí příkazu extends, takže implementace rozhraní se provádí pomocí příkazu implements.
interface iPotrebne
{
  const POCET = 10;
}

class Auto implements iPotrebne // implementace rozhrani do tridy
{
  
}
- Teď si to ukážem trochu v praxi a vytvoříme si deklaraci (prototyp) funkce v rozhraní. To znamená, že vytvoříme pouze název funkce a její parametry a ukončíme středníkem. Pro třídu to bude znamenat to, že musí vytvořit úplně stejnou funkci, ale obsah už může být jakýkoli.
interface iPotrebne // nase rozhrani
{
  const POCET = 10; // verejna konstanta
  
  // dve definice funkci (musi byt bez logiky)
  public function vypis($text);
  public static function zobrazPocet();
}

// trida Auto, ktera implementuje rozhrani iPotrebne
class Auto implements iPotrebne
{
  // funkce stejna jako v rozhrani, jen ji doplnime svoji logiku
  public function vypis($text) { echo $text; }
  
  // opet to same, jen se jedna o statickou funkci
  public static function zobrazPocet() { echo iPotrebne::POCET; }
}

$a = new Auto();
$a->vypis("ahoj"); // vypise "ahoj"
Auto::zobrazPocet(); // vypise 10
- Jedna třída může obsahovat i více rozhraní, potom je nutné, aby třída obsahovala i funkce z druhého rozhraní.
interface iA
{
  public function zapis();
}

interface iB
{
  public function napis();
  public function zapis(); // fatal error, prekryva se funkce z rozhrani iA !!
}

// trida, implementujici dve rozhrani
class T1 implements iA, iB
{
  public function zapis() { echo "OK"; } // z rozhrani iA
  public function napis() { echo "OK"; } // z rozhrani iB
}
- Můžete si všimnout, že na rozdíl od extends, kde se dědí pouze jedna třída, tak u implements lze použít více, než jedno rozhraní.
- Aby toho však nebylo málo, tak rozhraní může též dědit rozhraní pomocí extends, zde je potom pravidlo trochu jiné, protože jedno rozhraní může dědit hned z několika rozhraní.
// mame tyto 3 rozhrani a kazde ma jednu definici funkce
interface iA { public function F1(); }
interface iB { public function F2(); }
interface iC { public function F3(); }

// hlavni rozhrani, ktere dedi 3 rozhrani + prida vlastni definici
interface iHlavni extends iA, iB, iC
{
  public function F4();
}

// trida, ktera implementuje hlavni rozhrani, takze musi obsahovat vsechny funkce
class Main implements iHlavni
{
  public function F1() { echo "F1"; }
  public function F2() { echo "F2"; }
  public function F3() { echo "F3"; }
  public function F4() { echo "F4"; }
}
- Podle mého názoru je škoda, že třída nemůže dědit více tříd než jedno, ale co se dá dělat. I když vícenásobné dědění je nekdy i oříšek s náročností a ošetření chyb.
- Koho by toto zajímalo, tak jak tohle částečně obejít se řeší v druhé části lekci i třídách.

- Jako poslední co si ukážem bude rozhraní, které ma definici funkce s prvotními hodnotami.
- Rozdíl zde bude ten, že ve třídě implementovaná funkce musí mít též hodnoty.
// rozhrani o funkci, kde parametry maji nastavene hodnoty
interface iA
{
  // funkce s prvotnimi hodnotami NULL
  public function vypis($text = null, $povolit = null);
  
  // funkce s referencni promennou
  public function vrat(&$ref);
}

class Main implements iA
{
  // funkce musi mit take prvotni hodnoty (je jedno jake)
  public function vypis($text = "bez textu", $povoleno = true)
  {
	if ($povoleno) echo $text;
  }
  
  // parametr funkce musi byt tez reference
  public function vrat(&$vrat) { $vrat = 10; }
}
- Na závěr bych doplnil, že použitím rozhraní si kód nijak nezlepšíte ani neurychlíte. Je to pouze pro lepší přehlednost a bezpečnost tím, že třída prostě musí ty funkce mít, jinak není schopná fungovat a pokud někdo cizí se na váš kód podivá, tak jasně vidí, co všechno ta třída musí obsahovat.


Dobrovolný domácí úkol


1) Vytvořte si finální třídu User, která bude objektem pro každého uživatele a bude obsahovat jeho jméno a věk. Poté si vytvořte rozhraní iMainFce, kde budou definice funkcí addUser($objUser) pro přidání objektu každého uživatele (třídy Users), printUsers() pro vypsání jednotlivých uživatelů se jménem a věkem z pole a definici refCountUsers(&$users) pro referenci o počtu všech uživatelů. Nyní si vytvoříme hlavní finální třídu Lists, která bude implementovat naše rozhraní. Logiku programu už zapište sami. Na konec si vytvoříme objekt třídy Lists a přidáme 3 uživatelé do pole a vypíšem všechny uživatelé z pole a velikost pole.

interface iMainFce // nase rozhrani a jeho definice
{
  public function printUsers();
  public function addUser($objUser);
  public function refCountUsers(&$users);
}

final class User // finalni trida User
{
  // uchovava jmeno a vek uzivatele
  private $name;
  private $age;
  
  // zada se uzivatel pres konstruktor
  public function __construct($name, $age)
  {
	$this->name = $name;
	$this->age = $age;
  }
  
  // gettry
  public function getName() { return $this->name; }
  public function getAge() { return $this->age; }
}

// hlavni trida Lists, ktera implementuje nase rozhrani
final class Lists implements iMainFce
{
  private $arr; // pole
  
  // logika funkci z implementace
  public function addUser($objUser) { $this->arr[] = $objUser; }
  
  public function refCountUsers(&$users) { $users = count($this->arr); }
  
  public function printUsers()
  {
	foreach ($this->arr as $usr)
	{
	  echo $usr->getName()." (".$usr->getAge().")
"; } } } $seznam = new Lists(); // vytvorime 3 uzivatele $seznam->addUser(new User("Jan", 22)); $seznam->addUser(new User("Lenka", 24)); $seznam->addUser(new User("Petr", 26)); $seznam->printUsers(); // vypisem pole $seznam->refCountUsers($pocet); // vytvorime si promennou z poctem uzivatelu echo $pocet; // vypisem 3


This page was loaded in 0.514958 seconds. © 2011-2025 by mimic | mimic.php5.cz
ICQ contact is 204-517-399