Interfészek alkalmazása az OOP-ban PHP-ben

Tehát már megállapítottuk, hogy az interfészek jó módja annak, hogy ellenőrizzük, egy osztály minden szükséges metódusa megvalósult-e.

Nézzünk meg egy még gyakorlatiasabb példát. Tegyük fel, van egy osztályunk, ami alakzat objektumok tömbjét tárolja:

FiguresCollection.php<?php
  class FiguresCollection
  {
    private $figures = []; // tömb az alakzatoknak
  }
?>

Valósítsuk meg osztályunkban a addFigure metódust objektumok gyűjteménybe való hozzáadásához:

FiguresCollection.php<?php
  class FiguresCollection
  {
    private $figures = [];
    
    // Paraméterként egy alakzat objektumot adunk át:
    public function addFigure($figure)
    {
      $this->figures[] = $figure;
    }
  }
?>

Nyilvánvaló, hogy arra számítunk, hogy a addFigure metódus paramétereként egy alakzat objektum lesz átadva. Azonban erre nincs semmiféle ellenőrzés!

Használjunk típus hint-et és explicit adjuk meg az objektumok típusát Figure-ként:

FiguresCollection.php<?php
  class FiguresCollection
  {
    private $figures = [];
    
    public function addFigure(Figure $figure)
    {
      $this->figures[] = $figure;
    }
  }
?>

Értsük meg, mit tettünk.

Ha a Figure egy valóban létező osztály lenne, akkor a metódus paraméterébe át tudnánk adni az adott osztály objektumait, valamint annak leszármazottait is.

Nálunk azonban a Figure egy interfész. Ilyen esetben a hint azt jelenti, hogy a metódus paraméterébe csak azon osztályok objektumai adhatók át, amelyek megvalósítják az interfészünket.

Próbáljunk meg létrehozni egy objektumot az osztályunkból és adjunk hozzá alakzatokat:

index.php<?php
  $figuresCollection = new FiguresCollection;
  
  // Adjunk hozzá pár négyzetet:
  $figuresCollection->add(new Quadrate(2));
  $figuresCollection->add(new Quadrate(3));
  
  // Adjunk hozzá pár téglalapot:
  $figuresCollection->add(new Rectangle(2, 3));
  $figuresCollection->add(new Rectangle(3, 4));
?>

Bármely más osztály objektumának hozzáadása hibához fog vezetni:

index.php<?php
  $figuresCollection = new FiguresCollection;
  
  class Test {}; // valami más osztály
  $figuresCollection->add(new Test); // hibát fog adni
?>

Mit ad gyakorlatilag nekünk ez az ellenőrzés: mivel a gyűjteménybe hozzáadott összes alakzat megvalósítja a Figure interfészt, biztosak lehetünk benne, hogy mindegyikük rendelkezik a getSquare metódussal és a getPerimeter metódussal.

Lehetséges, hogy a jövőben a négyzet és téglalap mellett megjelenik például egy háromszög is. Ebben az esetben a háromszögnek is lesznek getSquare és getPerimeter metódusai.

Gyakorlatilag ez a következőt jelenti: a FiguresCollection osztályban készíthetünk például egy getTotalSquare metódust, amely megtalálja a gyűjtemény alakzatainak teljes területét. Ebben a metódusban bejárjuk ciklussal az alakzatok tömbjét és minden egyes alakzaton meghívjuk a getSquare metódust.

Mivel minden alakzat megvalósítja a Figure interfészt, 100%-ig biztosak lehetünk abban, hogy minden alakzat rendelkezik ezzel a getSquare metódussal.

Tehát itt a metódus megvalósítása:

php<?php
  class FiguresCollection
  {
    private $figures = [];
    
    public function addFigure(Figure $figure)
    {
      $this->figures[] = $figure;
    }
    
    // Keressük meg a teljes területet:
    public function getTotalSquare()
    {
      $sum = 0;
      
      foreach ($this->figures as $figure) {
        $sum += $figure->getSquare(); // a getSquare metódust használjuk
      }
      
      return $sum;
    }
  }
?>
Задание 1

Ne kukucskálj az én kódom mögé, valósítsd meg ugyanezt a FiguresCollection osztályt.

Задание 2

Add hozzá a FiguresCollection osztályhoz a getTotalPerimeter metódust az összes alakzat összperiméterének megtalálásához.