Programowanie obiektowe w PHP #2
W pierwszej części kursu programowania obiektowego w PHP, opowiedziałem, co to jest programowanie obiektowe, jakie ma zalety i jak tworzyć klasy. W tej części powiem o innych typach klas, które spowodują, że nasze aplikacje w PHP będą jeszcze bardziej elastyczne, a także o statycznych elementach dla naszych klas.
W pierwszej części kursu programowania obiektowego w PHP, opowiedziałem, co to jest programowanie obiektowe, jakie ma zalety i jak tworzyć klasy. W tej części powiem o innych typach klas, które spowodują, że nasze aplikacje w PHP będą jeszcze bardziej elastyczne, a także o statycznych elementach dla naszych klas.
Klasy abstrakcyjne
Na początek omówimy klasy abstrakcyjne. Czym one są? Można je nazwać „niepełnosprawnymi”. Dlaczego? Bo same nie mogą działać. Zapytacie pewnie, po co nam takie „niedorozwinięte” klasy. Żeby to wytłumaczyć wrócę do poprzedniej lekcji. Stworzyliśmy tam klasę Grupa. Tak naprawdę sama Grupa nic nie znaczy. Nie dostarcza nam informacji o tym, kto należy do tej grupy, czym zajmują się jej członkowie. Tak naprawdę wiemy tylko, że klasa ta gromadzi informacje o osobach w jakiś sposób ze sobą związanych. Jest to więc klasa abstrakcyjna. Ale jak z takiej klasy zrobić pełnowartościową klasę? Wystarczy stworzyć drugą klasę, która po takiej abstrakcyjnej będzie dziedziczyła. Stworzymy więc klasę, która będzie obsługiwała dane grupy przedszkolaków uczących się rysunków. Najpierw więc wprowadźmy drobną modyfikację do klasy Grupa.
A teraz stworzymy klasę dla przedszkolaków z grupy żabek uczących się rysunków.
Jak widzimy, klasa abstrakcyjna bardzo ułatwiła nam zadanie. W konstruktorze klasy odwołujemy się do konstruktora „rodzica”. Dzięki temu ustawiamy nazwę grupy. Następnie dodajemy poziom edukacji, a także przedmiot jakiego się uczą.
W klasie tej odwołujemy się do funkcji, która należy do „rodzica” poprzez słowo klucz parent i operator podwójnego dwukropka (::).
Klasy finalne
Przeciwieństwem klasy abstrakcyjnej jest klasa finalna (końcowa). Jej z kolei nie można już rozszerzać poprzez tworzenie klas po niej dziedziczących. Aby taką klasę zdefiniować, wystarczy dodać przed słowem class, słowo final. Dlaczego mamy możliwość ograniczania rozwoju klas? Czasami stworzenie klasy dziedziczącej po jakiejś klasie, może być niebezpieczne lub powodować nieprawidłowe działanie. Kiedy? Np. kiedy klasa ma wszystkie elementy (metody i zmienne) zdefiniowane jako prywatne. Wtedy nie mogą one być używane przez klasy dziedziczące. A czasami po prostu autor kodu z jakichś względów nie chce, aby klasa była rozszerzana. W praktyce klasy finalne spotyka się dość rzadko. Niemniej jednak ich znajomość jest wskazana.
Interfejsy
Definiując interfejs, ustalamy, jakie metody klasa implementująca dany interfejs musi zawierać. Np. interfejs o nazwie Cache_Interface (w informatyce tłumaczone z ang. jako pamięć), musi zawierać dwie metody publiczne: setData, getData. Stwórzmy więc taki interfejs. Przypomnę, że interfejs nie może zawierać definicji zmiennych, a jedynie stałych.
Jak pewnie zauważyliście, w interfejsach nie tworzymy także ciała klasy.
Interfejsy, tak jak klasy („normalne” i abstrakcyjne), mogą po dziedziczyć – jednak tylko po innych interfejsach. Stworzymy teraz nową wersję interfejsu Cache_Interface, która będzie zawierała definicję jeszcze jednej metody. Ale żeby wykorzystać dziedziczenie, nazwiemy ten interfejs CacheExt_Interface (skrót od Cache Extended – pamięć rozszerzona). Będzie on dziedziczył po interfejsie Cache_Interface.
Ok. Mamy już interfejs. Teraz trzeba tylko z niego skorzystać. Aby klasa implementowała interfejs, należy dodać po jej nazwie słowo kluczowe implements i nazwę interfejsu. Stworzymy więc klasę Cache, która będzie opierała się o interfejs CacheExt.
Ważne jest to, że możemy definiować także inne metody niż te ustalone przez interfejs, jednak te z interfejsu są obowiązkowe. Dlatego nie należy przesadzać z tworzeniem zbyt szczegółowych interfejsów.
Interfejsy są traktowane przez interpreter PHP jako normalne klasy, więc nie mogą one mieć takich samych nazw jak klasy.
Na marginesie dodam, że pisaniem profesjonalnej klasy pamięci zajmiemy się już niedługo poza tym kursem.
Elementy statyczne
Ale to nie koniec na dzisiaj :) Powiem jeszcze o statycznych elementach klas, ponieważ jest to temat bardzo potrzebny i przydatny.
Elementy statyczne, to takie, które w rzeczywistości nie bardzo potrzebują innych elementów klasy w której się znajdują. Definiujemy je poprzez dodanie słówka static zaraz po modyfikatorze destępu (public, private, protected). Do elementów statycznych odwołujemy się poprzez samą nazwę klasy i następujący po niej operator podwójnego dwukropka.
Pozostaje jednak pytanie, kiedy używamy statycznych elementów klas? Zacznijmy od najprostszego przykładu. Potrzebujemy pewnego rodzaju „pojemnik” na funkcje, które tematycznie są ze sobą powiązane. Np. funkcje do obsługi modyfikowania ciągów string. Stwórzmy klasę Strings, która będzie zawierała kilka funkcji wywołujących istniejące już w PHP funkcje modyfikujące obiekty typu string. (Nie będziemy tworzyć nic nowego, ponieważ chodzi tutaj o istotę metod statycznych)
W praktyce taka klasa nie ma sensu, ponieważ wykorzystuje ona tylko funkcje twórców PHP. Można by było modyfikować obiekty przez referencję. Wtedy taka klasa miałaby już większy sens.
Takie „pojemniki” na funkcje są dość często stosowane we frameworkach PHP dla funkcji modyfikacyjnych. Czyli stworzyliśmy dość praktyczny kod.
Metody statyczne możemy stosować wszędzie tam, gdzie reszta ciała klasy nie jest tej metodzie do niczego potrzebna. Bardziej praktycznym, ale trochę trudniejszym do zrozumienia na początku przykładem są klasy typu singleton, czyli takie których może powstać tylko jeden egzemplarz. Powiemy o nich w jednej z dalszych części tego kursu.
Ale wracając do „statyki”. Każda metoda w ciele klasy, czy poza nim, może korzystać z elementów statycznych. Pozostaje kwestia tego, jak się do niej odwołać. Poza ciałem klasy jest tylko jeden sposób na to: NazwaKlasy::ElementStatyczny. Wewnątrz klasy możemy skorzystać z podanego przed chwilą sposobu, ale możemy też skorzystać (polecam to!) ze słowa self, które określa, że korzystamy z elementów statycznych klasy, wewnątrz której zostało to słowo-klucz użyte. Np. self::ElementStatyczny.
Przypomnę jeszcze, że wszystko co statyczne podlega także „władzy” modyfikatorów dostępu.
Na koniec przywołam jeden przykład z artykułu PHP: Obsługa szablonów (#2). Zamieściłem tam bardzo prostą klasę Arr, która obsługuje tablice.
Teraz przy jej użyciu dodamy do tablicy kilka elementów z indeksami, a potem ją wyświetlimy.
Na dzisiaj to już koniec. Zapraszam do czytania kolejnych części :)