Wirtualny świat obiektów. Programowanie obiektowe w PHP.

Programowanie obiektowe jest paradygmatem programowania, który od kilkunastu ostatnich lat zyskuje na popularności w branży informatycznej. Jego głównym celem jest tworzenie kodu opartego na tzw. Obiektach, czyli takich strukturach, które zawierają atrybuty – inaczej nazywane właściwościami, które odgrywają rolę zmiennych oraz metody, czyli funkcje znajdujące się w danej klasie, które służą do wykonywania pewnych operacji lub manipulowania właściwościami, o których wcześniej wspomnieliśmy. W PHP, który jest bardzo popularnym językiem programowania aplikacji internetowych, programowanie obiektowe stało się standardem w wersji 5.

W programowaniu obiektowym w języku PHP kluczowe są klasy. Klasy są to szablony – jakby przepisy, na których podstawie tworzone są obiekty, czyli instancje danej klasy.  Każda klasa zawiera definicje właściwości oraz metod, które będą udostępnione obiektom utworzonym na jej podstawie. Dzięki temu programista ma możliwość łatwego tworzenia i zarządzania wieloma obiektami na raz, a ich właściwości oraz funkcjonalności mogą być zmieniane w czasie rzeczywistym. Dodatkowo programowanie obiektowe w PHP umożliwia programistom tworzenie bardziej skalowalnych i elastycznych aplikacji, co jest szczególnie istotne w przypadku dużych aplikacji. Pozwala także na zwiększenie czytelności i łatwości utrzymania takiego kodu, poprzez organizowanie go w logiczne i hermetyczne moduły, które mają odzwierciedlać obiekty oraz działania biznesu występujące w świecie realnym.

W tym artykule omówimy podstawowe elementy programowanie obiektowego na podstawie przykładów z języka PHP, takie jak klasy, obiekty, dziedziczenie, interfejsy, klasy abstrakcyjne i polimorfizm oraz pokażemy jak można z nich korzystać w praktyce.

KLASY

Klasy stanowią podstawową jednostkę programowania obiektowego w PHP. Są to szablony, na podstawie których tworzone są obiekty. Każda klasa zawiera definicje własnych właściwości oraz metod, które będą udostępnione obiektom utworzonym na jej podstawie.

Definicja klasy rozpoczyna się od użycia przez nas słowa kluczowego „class”, po którym należy zdefiniować nazwę klasy. Konwencja nazewnictwa w PHP, a powinniśmy stosować dobre praktyki mówi, że nazwa klasy powinna rozpoczynać się wielką literą, np. klasa reprezentująca fakturę sprzedażową powinna nazywać się „FakturaSprzedazowa”. Nie możemy używać w kodzie PHP polskich znaków, dlatego nazwa klasy ich nie zawiera – ale ogólnie przyjęte jest, aby przy tworzeniu nazw dla zmiennych czy klas używać słów z języka angielskiego. Dla jasności przykładu posłużymy się tu nazwami polskimi. Następnie po zadeklarowaniu nazwy klasy w klamrach {} definiujemy właściwości oraz metody np.: W powyższym przykładzie zdefiniowaliśmy klasę „FakturaSprzedazowa”, która posiada dwie właściwości: publiczną „$id” oraz prywatną „$numerFaktury”. Ponadto klasa zawiera dwie metody: publiczną „pobierzNumerFaktury” oraz prywatną „ustawNumerFaktury”.

Atrybuty klasy przechowują dane, na których operują metody klasy. W naszym przykładzie właściwość „$id” jest publiczna, co oznacza że można się do niej odwołać z poziomu innych klas lub funkcji. Natomiast „$numberFaktury” jest prywatna, co oznacza, że jest ona dostępna tylko z poziomu klasy, w której została zdefiniowana.

Metody klasy to funkcje, które wykonywane są na obiektach danej klasy. Metody publiczne są dostępne z poziomu innych klas i funkcji, natomiast metody prywatne są dostępne tylko z poziomu klasy, w której zostały zdefiniowane.

Podsumowując, klasy są podstawowymi jednostkami programowania obiektowego w PHP. Zawierają definicje właściwości oraz metod, które są wykorzystywane do tworzenia obiektów. Definicja klasy rozpoczyna się słowem kluczowym „class”, po którym następuje nazwa klasy oraz definicje właściwości i metod pomiędzy klamrami {}.

DZIEDZICZENIE

Dziedziczenie to ważny element w programowaniu obiektowym. Pozwala on na tworzenie klas dziedziczących po innych klasach. Klasa, która dziedziczy, nazywana jest klasą pochodną, a klasa po której dziedziczy, jest to klasa bazowa.

Dziedziczenie pozwala na tworzenie hierarchicznej struktury klas, w której klasy pochodne dziedziczą właściwości oraz metody po klasie bazowej. Dzięki temu mechanizmowi możemy uniknąć powtarzającego się kodu czyli ma tu zastosowanie metoda DRY oraz zwiększyć czytelność i elastyczność kodu.

Aby dziedziczyć po innej klasie, należy użyć słowa kluczowego „extends” i podać nazwę klasy bazowej. Przykładowo, jeśli chcemy stworzyć klasę dziedziczącą po klasie „Faktura”, możemy to zrobić w następujący sposób: W powyższym przykładzie klasa „FakturaSprzedazowa” dziedziczy – czy inaczej rozszerza klasę „Faktura”. Klasa dziedzicząca ma dostęp do właściwości i metod klasy bazowej, jednak może posiadać również własne właściwości i metody.

W PHP mechanizm dziedziczenie pozwala niestety na rozszerzenie tylko jednej klasy na raz.

Istnieją jednak języki, gdzie mechanizm dziedziczenie pozwala dziedziczyć po wielu klasach co powinno być standardem i kierunkiem, w którym rozwój każdego języka powinien podążać.

Podsumowując, dziedziczenie w programowaniu obiektowych w PHP to proces tworzenia klas pochodnych, które dziedziczą właściwości oraz metody klasy bazowej. Dzięki temu unikamy powtarzającego się kodu i tworzymy hierarchię logicznie ułożonych klas. Klasa dziedzicząca ma dostęp do właściwości oraz metod klasy bazowej, ale może również posiadać własne. Dziedziczenie pozwala na rozszerzenie funkcjonalności klasy bazowej i tworzenie bardziej elastycznego kodu.

INTERFEJSY

Interfejsy w programowaniu obiektowym to sposób na określenie, jakie metody powinna implementować dana klasa. W PHP interfejs jest zbiorem deklaracji metod bez ich implementacji. Klasa, która implementuje dany interfejs, musi zaimplementować wszystkie metody zawarte w interfejsie.

Interfejsy w PHP tworzymy przy pomocy słowa kluczowego „interface”, a następnie podajemy nazwę naszego interfejsu. Wewnątrz interfejsu definiujemy metody, ale nie ich implementujemy. Oto przykład:Klasa, która implementuje powyższy interfejs, musi zaimplementować dwie metody – „sendMessage()” i „receiveMessage()” – zgodnie z ich wcześniejszą deklaracją w interfejsie.

Implementacja interfejsów w PHP odbywa się za pomocą słowa kluczowego „implements”. Oto przykład:Klasa „EmailMessegner” implementuje interfejs „MessegnerInterface”, co oznacza, że musi zaimplementować obie metody zadeklarowane w interfejsie. W typ przypadku metody są odpowiedzialne za wysyłanie i odbieranie wiadomości e-mail.

Interfejsy mają jeszcze jedną ważną cechę. W przeciwieństwie do mechanizmu dziedziczenia w języku PHP, klasa może implementować wiele interfejsów co jeszcze bardziej ułatwia tworzenie pewnej logicznej hierarchii klas. Co więcej interfejsy podobnie jak klasy można rozszerzać jak np. na poniższym przykładzie: Dzięki temu mechanizmowi możemy tworzyć również hierarchię interfejsów a w powyższym przykładzie, jeżeli klasa będzie implementować interfejs „MessegnerInterface” oprócz metod tego interfejsu będzie musiała również implementować metody „ExampleInterface”.

Interfejsy w PHP pozwalają na łatwe tworzenie klas, które będą działać zgodnie z ustalonymi odgórnie przez interfejsy wymaganiami. Dzięki temu kod może być bardziej czytelny i elastyczny.[/vc_column_text]

KLASY ABSTRAKCYJNE

Klasy abstrakcyjne w programowaniu obiektowym to klasy, na podstawie których nie można tworzyć obiektów. Służą one jedynie jako szablony dla innych klas. Klasy abstrakcyjne pozwalają na definiowanie ogólnych metod i właściwości, które muszą zostać zaimplementowane w klasach dziedziczących.

Klasy abstrakcyjne w PHP tworzymy przy użyciu słowa kluczowego „abstract”. Oto przykład:Klasa „Animal” to klasa abstrakcyjna, która definiuje dwie metody – „eat()” oraz „makeSound()”.

Metoda „eat()” ma już zaimplementowaną swoją funkcjonalność, ale metoda „makeSound()” jest tylko deklaracją, która musi zostać zaimplementowana w klasach dziedziczących.

Klasy abstrakcyjne często są wykorzystywane jako klasy bazowe dla innych klas. Dzięki mechanizmowi dziedziczenia po klasie abstrakcyjnej, klasy dziedziczące muszą zaimplementować metody abstrakcyjne. Oto przykład: Klasy „Dog” i „Cat” dziedziczą po klasie abstrakcyjnej „Animal”. Ponieważ klasa „Animal” ma jedną metodę abstrakcyjną „makeSound()”, klasy pochodne muszą ją zaimplementować. W powyższym przykładzie klasy „Dog” i „Cat” implementują tę metodę w różny sposób.

Klasy abstrakcyjne pozwalają na zdefiniowanie wspólnych cech dla wielu klas pochodnych. Dzięki temu kod staje się bardziej czytelny i łatwiejszy w utrzymaniu. Klasy abstrakcyjne są szczególnie przydatne, gdy chcemy skonstruować pewną logikę i hierarchię klas, ale nie mamy jeszcze pełnego obrazu, jak powinny działać konkretne klasy dziedziczące. W takim przypadku możemy zdefiniować klasę abstrakcyjną jako szablon, a dopiero na dalszym etapie implementować funkcjonalności w klasach dziedziczących.

KLASY FINALNE

Klasy finalne to klasy, po których nie można dziedziczyć. Oznacza to, że nie można tworzyć klas pochodnych, które będą rozszerzać klasę finalną. W PHP klasy finalne definiujemy za pomocą słowa kluczowego „final”.

Oto przykład konstrukcji klasy finalnej w języku PHP: Klasa „ProductController” to klasa finalna, która nie może być rozszerzona przez inne klasy.

Jak widać jednak na powyższym przykładzie taka klasa może dziedziczyć po innej klasie, więc należy pamiętać, że klasa finalna może dziedziczyć po innej klasie, ale żadna klasa nie może dziedziczyć po niej.

Klasy finalne są szczególnie przydatne w sytuacjach, gdy chcemy zabezpieczyć pewne klasy przed dziedziczeniem. Może to być spowodowane np.:

– chcemy uniknąć nadmiernej złożoności hierarchii klas

– chcemy uniknąć nadpisywania istotnych metod lub właściwości klasy

Klasy finalne pozwalają na zabezpieczenie kodu przed niekontrolowanymi zmianami.Podsumowując – klasy finalne są przydatnym narzędziem w programowaniu obiektowym, pozwalającym na zabezpieczenie pewnych klas przed dziedziczeniem i utrzymanie kodu w czytelny sposób. Moim zdaniem, dopóki jakaś klasa faktycznie nie wymaga dziedziczenia, każda klasa domyślnie powinna być klasą finalną.

PODSUMOWANIE

Kończąc – programowanie obiektowe i jego elementy to bardzo ważne komponenty dzięki czemu można budować aplikacje czytelne, elastyczne na rozwój oraz łatwe w utrzymaniu. Należy jednak uważać, aby korzystając z tego rodzaju budowy oprogramowania nie wpaść w pułapkę zbyt skomplikowanych logik i hierarchii, co może powodować że kod przestanie być czytelny, a powinien być czytelny przede wszystkim dla ludzi, którzy będą z nim pracować. Także korzystajmy z programowania obiektowego, ale nie zapominajmy aby myśleć czy dana logika i hierarchia nie jest zbyt skomplikowana.