Jdi na navigaci předmětu

Objektově orientované programování

Základní principy a pojmy

  • zapouzdření - těsný vztah mezi daty a operacemi
  • dědičnost - sdílení stejných vlastností
  • polymorfismus - různá implementace v potomcích stejného rodiče

Základní principy a pojmy

  • třída - definuje formát dat a operace
  • objekt (instance) - realizace třídy, konkrétní hodnoty atributů

V některých jazycích je i třída objektem.

OOP v PHP

  • třídní OOP (narozdíl od prototypové v plain JS)
  • viditelnost - private, protected, public
  • abstract a final třídy a metody
  • magické metody
  • rozhraní, traity
  • klonování
  • type hinting

Definice třídy

  • klíčové slovo class

      class Account {
        protected $number;
        protected $amount;
        protected $transactions = [];
        public function addTransaction($transaction) { ... }
        public function getTransactions() { ... }
        ...
      }

Instanciace, přiřazení

  • instanciace pomocí operátoru new
  • přiřazení referencí
  • kopírování explicitně pomocí operátoru clone
$account = new Account; // pokud se konstruktoru nepředávají argumenty nemusí být ()
$card = new Card(12345);
$skim = clone $card;

Třída vs instance

  • instance
    • instanční atributy - zvlášť pro každou instanci
    • metody
  • třída
    • třídní atributy - sdílené pro všechny instance (static)
    • metody - nemohou pracovat s instancí
    • konstanty

Odkazování na třídu a instanci

  • instance
    • názvem proměnné (proměnná = reference) - zvenku
    • speciální proměnná $this - zevnitř, reprezentuje volající instanci
  • třída
    • pomocí názvu třídy - zvenku i zevnitř
    • zevnitř pomocí self nebo static

Přistupování k atributům a metodám

  • object operator ->
  • scope resolution operator :: (Paamayim Nekudotayim)

Přistupování k atributům a metodám

class Card
{
  ...
  function getPin() {
    return substr($this->number,0,4); // zevnitř $this->...
  }
}
$number = $card->getNumber(); // zvenku $promenna->...

Přistupování k atributům a metodám

class Card
{
  public static function issue() {
    return new self; // vrátí vlastní instanci
  }
}
$newCard = Card::issue(); // zvenku třída::...

Viditelnost

  • private - přístup pouze zevnitř třídy
  • protected - přístup z třídy a jejích potomků
  • public (výchozí) - bez omezení

Měnitelnost

  • readonly - do atributu lze zapsat jen v rámci kontruktoru

Instanční atributy

  • object operator ->

    class Account { public $number; }
    // obvyklé použití, před number není $
    echo $account->number;
    // proměnná proměnná
    $property = 'number';
    echo $account->$property;

Třídní atributy

  • modifikátor static
  • přístup pomocí scope resolution operator ::
class Bank {
  static $accounts;
}
// z venku
Bank::$accounts
// zevnitř
self::$accounts
// zevnitř - late static binding
static::$accounts

Konstanty

class Card {
  const TYPE_VISA = 1;
  const TYPE_MASTERCARD = 2;
  const DEFAULT_HELLO = "Ahojky!!!";
}

echo Card::TYPE_VISA;
  • od PHP 8.3 mohou být typovány
class Card {
  const int TYPE_VISA = 1;
  const int TYPE_MASTERCARD = 2;
  const string DEFAULT_HELLO = "Ahojky!!!";
}

echo Card::TYPE_VISA;

Instanční a třídní metody

  • platí totéž, co u atributů
class Card {
  public function getNumber() {
    return $this->number;
  }

  public static function getTypes() {
    return [
      self::TYPE_VISA, self::TYPE_MASTERCARD
    ];
  }
}

Konstruktor

  • inicializace objektu, nepovinná
  • magická metoda __construct

    class Order {
      protected static int $sequence = 0;
      protected int $id;
      protected string $name;
      public function __construct(string $name) {
        $this->id = ++static::$sequence;
        $this->name = $name;
      }
    }
  • Od php 8.0 může být atribut deklarován v konstruktoru (pomocí slov private, protected nebo public)

    class Order {
      protected static int $sequence = 0;
      protected int $id;
      public function __construct(protected string $name) {
        $this->id = ++static::$sequence;
      }
    }

Destruktor

  • uvolnění objektu (deinicializace), používá se zřídka
  • magická metoda __destruct
  • volán garbage collectorem
  • bez argumentů

Dědičnost

  • vztah mezi třídami
  • specializace (rodič → potomek)
  • generalizace (potomek → rodič)

Dědičnost

class Card {
  protected $number;
}

class DebitCard extends Card {
  protected $limit;
}

class CreditCard extends Card {
  protected $dueDay;
}

Dědičnost - přístup k rodiči

  • explicitně: klíčové slovo parent a scope resolution operator

    parent::$number  // přístup k atributu
    parent::lock()   // přístup k metodě
  • pokud není atribut nebo metoda překryta v potomkovi, může přistupovat i přes potomka

    $child->number   // přístup k atributu
    $child->lock()   // přístup k metodě

Dědičnost - konstruktor

  • obvykle voláme rodičovský konstruktor na začátku konstruktoru potomka
  • pokud není v potomkovi implementovaný, volá se rodičovský automaticky

    function __construct() {
      parent::__construct(); // lze předat argumenty
      $this->dueDay = 20;
    }

Dědičnost - destruktor

  • obvykle voláme na konci, po provedení operací pro potomka

    function __destruct() {
      // uvolnění dat potomka apod.
      parent::__destruct();
    }

Dědičnost - self, late static binding

Pozor na jakou třídu ukazuje self a static.

class ParentClass {
    public function hello():void {
        echo "Hello from parent class" . PHP_EOL;
    }

    public function callSelf(): void {
        self::hello();
    }

    public function callStatic(): void {
        static::hello();
    }
}

class ChildClass extends ParentClass {
    public function hello():void {
        echo "Hello from child class" . PHP_EOL;
    }
}

$parent = new ParentClass();
$parent->callSelf();
$parent->callStatic();

$child = new ChildClass();
$child->callSelf();
$child->callStatic();

Užitečné třídy přímo v PHP

Autoloading

  • pokud třída není definovaná (známá) provádí se autoloading
  • lze nadefinovat funkci, která načtení třídy zařídí a program může běžet dál
  • úspora paměti, výkonu - načítá se jen to, co je potřeba

Autoloading