Menu

Interfejsy w PHP: implements, stałe i przykłady

Interfejs w PHP wymienia metody, które klasa obiecuje mieć: interface Shape { public function area(): float; }, a class Circle implements Shape musi wtedy zdefiniować area(). Poznaj typowanie interfejsami, implementowanie kilku interfejsów, stałe interfejsów, rozszerzanie interfejsów, interfejsy wbudowane, takie jak Countable, oraz interfejs vs klasa abstrakcyjna.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Interfejs w PHP deklaruje metody, które klasa obiecuje zapewnić, bez żadnego kodu: interface Shape { public function area(): float; }. Klasa, która pisze implements Shape, musi zdefiniować area(), a każda funkcja z typem Shape przyjmie tę klasę.

describe() nie wie i nie obchodzi go, którą klasę dostaje. Polega tylko na obietnicy, którą składa interfejs, więc nowa klasa Triangle implements Shape zadziała z nią bez zmiany choćby jednej linii.

Programowanie pod interfejs

Zwykły powód napisania interfejsu to pozwolić kodowi zależeć od zdolności, a nie od konkretnej klasy. Tutaj usługa zamówień przyjmuje dowolny Notifier, więc ten sam kod może wysyłać e-maile na produkcji i zbierać wiadomości w teście:

Implementowanie kilku interfejsów

Klasa rozszerza najwyżej jednego rodzica, ale może implementować tyle interfejsów, ile potrzebuje. Wymień je po implements, oddzielając przecinkami, i zdefiniuj metody ich wszystkich:

JsonSerializable to jeden z wbudowanych interfejsów PHP: jego implementacja decyduje o tym, co json_encode() zwraca dla obiektu.

Stałe interfejsów

Interfejs może deklarować stałe. Każda implementująca klasa je dziedziczy i można je odczytać przez nazwę interfejsu albo nazwę klasy:

W PHP 8.3 interfejsy nie mogą mieć właściwości, tylko metody i stałe. Metody mogą być statyczne: public static function fromArray(array $data): static; w interfejsie zobowiązuje każdą klasę do zdefiniowania tej metody statycznej. Dla stałego zestawu powiązanych wartości enum często pasuje lepiej niż lista stałych w interfejsie.

Interfejs może rozszerzać inne interfejsy

Interfejsy też używają extends i w przeciwieństwie do klas mogą rozszerzać kilka naraz. Klasa implementująca interfejs potomny musi zdefiniować metody całego łańcucha:

Interfejsy wbudowane: Countable, IteratorAggregate, Stringable

PHP ma interfejsy, które podłączają obiekty do języka. Countable sprawia, że działa count($obj), IteratorAggregate sprawia, że działa foreach, a Stringable jest implementowany automatycznie przez każdą klasę z metodą __toString():

Zapomniana metoda

Jeśli klasa deklaruje, że implementuje interfejs, ale brakuje jej metody, PHP zatrzymuje się z błędem krytycznym, który podaje nazwę brakującej metody:

Dodaj metodę total(), a skrypt się wykona. Klasa abstrakcyjna może zostawić metody interfejsu niezdefiniowane i to jest wyjście, które sugeruje komunikat błędu.

Interfejs vs klasa abstrakcyjna

Oba definiują metody, które klasa musi mieć, i oba mogą służyć jako typ. Różnią się tym, co jeszcze mogą zawierać, i tym, ile ich może użyć klasa:

InterfejsKlasa abstrakcyjna
Treść metodbrak (tylko sygnatury)metody abstrakcyjne i gotowe
Właściwościnietak
Konstruktormoże go zadeklarować, rzadko przydatnetak, z kodem
Widoczność metodtylko publicpublic, protected, private
Stałetaktak
Ile na klasędowolnie wiele (implements A, B, C)jedna (extends Base)
Typowe użyciezdolność: Exportable, Countablewspólny kod dla rodziny: Model, Controller

Dobrze się łączą: zdefiniuj interfejs do typowania i zaoferuj abstrakcyjną klasę bazową, która go implementuje ze wspólnym kodem. Klasy, które potrzebują innej bazy, nadal mogą implementować interfejs bezpośrednio.

Najczęściej zadawane pytania

Czym jest interfejs w PHP?

Listą sygnatur publicznych metod bez treści: interface Logger { public function log(string $msg): void; }. Klasa, która deklaruje implements Logger, musi zdefiniować każdą z tych metod, a każdy kod z typem Logger przyjmie tę klasę.

Czy klasa w PHP może implementować kilka interfejsów?

Tak. Wymień je po implements, oddzielając przecinkami: class File implements Readable, Writable, Countable. Klasa musi zdefiniować metody ich wszystkich. W ten sposób PHP pokrywa to, co w innych językach daje wielodziedziczenie.

Czym różni się interfejs od klasy abstrakcyjnej w PHP?

Interfejs deklaruje tylko metody publiczne (i stałe); nie ma właściwości ani kodu metod, a klasa może implementować wiele interfejsów. Klasa abstrakcyjna może zawierać właściwości, konstruktory i gotowe metody obok abstrakcyjnych, ale klasa może rozszerzać tylko jedną. Używaj interfejsu dla zdolności („można eksportować”), a klasy abstrakcyjnej dla wspólnego kodu w rodzinie klas.

Czy interfejs w PHP może mieć właściwości?

Nie w PHP 8.3: interfejs może zawierać sygnatury metod i stałe (const VERSION = 2;), ale nie właściwości. Deklaracje właściwości w interfejsach (property hooks) pojawiły się dopiero w PHP 8.4.

Jak sprawdzić, czy obiekt implementuje interfejs w PHP?

Użyj instanceof: $obj instanceof Countable jest prawdą, gdy klasa obiektu implementuje interfejs, bezpośrednio lub przez klasę rodzica. class_implements($obj) zwraca nazwy wszystkich interfejsów implementowanych przez klasę.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ