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

Programowanie obiektowe > Lekcja 7

abstract i final

Istnieje możliwość określenia, aby obiekt danej klasy nie mógł zostać stworzony. Wracając do przykładu z poprzedniej lekcji: tworzymy tam tylko obiekt na bazie klasy Adult lub Child, w których implementowane są dodatkowe metody. Klasa Person służy wyłącznie do dziedziczenia. W takiej właśnie sytuacji możemy zadeklarować ją jako abstrakcyjną.

Służy do tego słowo kluczowe abstract, a robimy to tak:

<?php

abstract class Person
{
    // ...
}

Próba utworzenia obiektu na bazie tej klasy zakończy się odpowiednim błędem:

<?php

abstract class Person
{
    // ...
}

$person = new Person();
Fatal error: Uncaught Error: Cannot instantiate abstract class Person in ...

Możemy również zadeklarować daną metodę jako abstrakcyjną. W takiej sytuacji jej deklaracja nie może zawierać ciała, czyli prościej mówiąc kodu do wykonania. Należy pamiętać, że aby tego dokonać, klasa również musi być zadeklarowana jako abstrakcyjna. Następnie dopiero w klasie rozszerzającej określamy ciało metod abstrakcyjnych. Co więcej, deklaracja musi być zgodna z późniejszymi implementacjami. Gdy więc określimy argumenty, ich typy czy typ zwracany w abstract, to metody w klasach dziedziczących muszą do tego pasować.

<?php

abstract class Person
{
    abstract public function getName(): string;
}

class Child extends Person
{
    public function getName(): string
    {
        return 'name';
    }
}

echo (new Child())->getName(); // result: name

Jaki to ma sens? W tym małym przykładzie niezbyt wielki, ale ogólnie rzecz biorąc, przygotowujemy pewny „szkielet” czy wzór. Dzięki temu wiemy odgórnie co uruchomić, jaki to da efekt, ale konkretne implementacje mogą być różne w danych klasach. Tu też przydaje się fakt, że możemy wstrzyknąć daną instancję przez argument metody, ustalając jako jego typ tylko klasę bazową.

final

final można poniekąd nazwać przeciwieństwem do abstract. Klasa zadeklarowana jako finalna nie może być dziedziczona. Próba zakończy się błędem.

<?php

final class Person
{
    // ...
}

class Child extends Person
{
    // ...
}
Fatal error: Class Child may not inherit from final class (Person) in ...

Istnieje także możliwość zadeklarowania metody jako finalnej. Wtedy po prostu nie może zostać nadpisana z klasy dziedziczącej.

<?php

class Person
{
    final public function getName(): string
    {
        return 'name';
    }
}

class Child extends Person
{
    public function getName(): string
    {
        return 'new name';
    }
}
Fatal error: Cannot override final method Person::getName() in ...

Uwaga

Zgodnie z zaleceniami standardu PSR-12, metodę jako finalną lub abstrakcyjną trzeba deklarować przed modyfikatorem widoczności. Taki też zapis zastosowałem w powyższych przykładach.

Poprzednia lekcja Następna lekcja

Udostępnij

  • Facebook
  • Twitter

Komentarze