Aktualizacja do najnowszego PHP 8 już jest! Zobacz główne zmiany.

Programowanie obiektowe > Lekcja 6

Dziedziczenie

Przed Tobą wielka rzecz w programowaniu obiektowym: dziedziczenie. Pewnie rozumiesz samo pojęcie dziedziczenia poza programowaniem (na przykład dziecko dziedziczy kolor oczu po matce). W programowaniu mamy podobnie: tworzona klasa może dziedziczyć po innej klasie, to znaczy przejąć jej właściwości oraz metody. Rzecz jasna klasa, która dziedziczy, również może mieć swoje metody czy właściwości.

A więc pozostając przy tematyce ludzi, spójrzmy na jakiś przykład. Wyobraź sobie, że mamy system obsługujący przychodnię lekarską i dzieci oraz osoby dorosłe muszą być inaczej potraktowane. Jest jednak sporo informacji, jakie należy zebrać na temat każdej osoby: imię i nazwisko, adres, PESEL i podobne. Zapiszmy to przy użyciu klasy bazowej i dwóch klas dziedziczących.

<?php

class Person
{
    public string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }
}

class Adult extends Person
{
    // code for adults
}

class Child extends Person
{
    public function checkVaccinations(): bool
    {
        // code...
        return true;
    }
}

$person = new Child('Jan Kowalski');
echo $person->getName(); // result: Jan Kowalski
var_dump($person->checkVaccinations()); // result: bool(true)

Klasę, po której chcemy dziedziczyć, określamy poprzez extends. Gdybyśmy dziedziczenia nie znali, to musielibyśmy skopiować część funkcji z jednej klasy do drugiej, co rodziłoby tylko problemy. Zawsze trzeba byłoby szukać, sprawdzać i zmieniać to samo w wielu miejscach

Ciekawostka

Co ciekawe, wspomniany w początkowej lekcji OOP, instanceof sprawdza także klasy, po których dziedziczy dana instancja. Czyli, idąc za powyższym przykładem, $person instanceof Person zwróci prawdę, pomimo że to obiekt klasy Child. Podobnie działa określenie typu argumentu. Wystarczy, że klasa będzie rozszerzała (lub implementowała, ale o tym kawałek dalej) wskazaną klasę i typ będzie zgodny. To całkiem pomocne, bo możemy dopuścić inne klasy, które łączy pożądana przez nas rzecz.

Nadpisywanie elementów

Ktoś pewnie zastanowi się teraz co stanie się, gdy utworzy w klasie metodę lub właściwość o takiej samej nazwie, jaka już istnieje w klasie, po której dziedziczy. Śpieszę z wyjaśnieniem, że element z klasy bazowej zostanie nadpisany. Innymi słowy, właściwość będzie miała taką wartość lub jak w klasie, która dziedziczy, a metoda będzie robiła to, co ta zapisana w klasie, która dziedziczy. Może trochę zawile to brzmi, ale chyba rozumiesz działanie. Jeśli nie to poniższy przykład na pewno wszystko rozjaśni:

<?php

class Person
{
    public string $name = 'Jan';
}

class Child extends Person
{
    public string $name = 'Marek';
}

$person = new Child();
echo $person->name; // result: Marek

Jeżeli jednak zaistnieje potrzeba wywołania nadpisanej metody z klasy bazowej, to jest taka możliwość. Wystarczy wywołać metodę z dopiskiem parent::.

<?php

class Person
{
    public function checkVaccinations()
    {
        // code...
        echo 'Check person!';
    }
}

class Child extends Person
{
    public function checkVaccinations()
    {
        parent::checkVaccinations();
        echo 'Check child!';
    }
}

$person = new Child();
$person->checkVaccinations(); // result: Check person!Check child!

Modyfikator protected

W tym miejscu muszę jeszcze na chwilkę wrócić do modyfikatorów dostępu. Wspominałem tam o protected i dziedziczeniu. Sprawa wygląda tak, że właściwość czy metoda oznaczona w ten sposób będzie widoczna w klasie bazowej, ale też w klasach ją rozszerzających. Jednak tylko wewnątrz, z zewnątrz dostęp daje wyłącznie public. Z private widoczność jest ograniczana tylko do klasy deklaracji. Przykładowo:

<?php

class Person
{
    private string $name;
    
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    
    protected function getName(): string
    {
        return $this->name;
    }
}

class Child extends Person
{
    public function showName()
    {
        echo $this->getName(); // result: Andrzej
        echo $this->name; // result: warning, undefined property 
    }
}

$person = new Child('Andrzej');
echo $person->showName();
echo $person->getName(); // result: fatal error

Mam nadzieję, że udało Ci się zrozumieć dziedziczenie, choć dopiero w praktyce poznasz, jakie daje to możliwości. To bardzo przydatna sprawa, idealna do wykorzystania w naprawdę wielu miejscach. Momentami problematyczne może wydawać się to, że nie widzisz w jednym miejscu, jakie metody ma dana klasa. Dlatego właśnie warto programować w IDE, które wszystko analizuje i podpowiada :)

Poprzednia lekcja Następna lekcja

Udostępnij

  • Facebook
  • Twitter

Komentarze