Programowanie obiektowe > Lekcja 7
abstract i final
Ostatnia modyfikacja: 01.06.2021
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.
Komentarze