2.1 Podstawowe koncepcje OOP
U podstaw podejścia obiektowego do programowania leży paradygmat OOP. To sytuacja, gdy wszystkie elementy programu są traktowane jako obiekty. Obiekty — to dane + metody/funkcje, które z tymi danymi coś robią.
Można też powiedzieć, że obiekt ma stan i zachowanie. Stan obiektu jest zapewniany przez jego dane, które są przechowywane w jego wewnętrznych zmiennych. Zachowanie obiektu — to zbiór wszystkich działań, które wykonują jego metody.
W średniej wielkości programie jest wiele tysięcy obiektów, w dużym — miliony. Aby jakoś zmniejszyć chaos, postanowiono uporządkować obiekty w klasy, a klasy — w pewną hierarchię.
To ciekawe! Koncepcja hierarchii klas została zaczerpnięta ze świata zwierząt, gdzie są ludzie, którzy są naczelnymi, którzy są ssakami itd.
Każdy obiekt ma klasę, za pomocą której jest tworzony. Z jednej strony, klasa — to pewien szablon obiektu, z drugiej — to samodzielny obiekt z własnymi cechami (o nich poniżej).
Aby lepiej zrozumieć koncepcję klas, zapoznaj się z następującymi definicjami:
Klasa:
Klasa — to szablon lub schemat do tworzenia obiektów, który definiuje atrybuty i metody charakterystyczne dla wszystkich obiektów tego typu. Klasy pozwalają organizować dane i funkcje obsługujące te dane w jedną całość.
Obiekt:
Obiekt — to instancja klasy. Każdy obiekt posiada stan (definiowany przez atrybuty) i zachowanie (definiowane przez metody).
Enkapsulacja:
Enkapsulacja polega na ukrywaniu wewnętrznej implementacji klasy i zapewnieniu interfejsu do interakcji z obiektami tej klasy. To pomaga chronić dane i zarządzać dostępem do nich.
Dziedziczenie:
Dziedziczenie pozwala jednej klasie (dziedziczącej) odziedziczyć atrybuty i metody innej klasy (rodzica). To wspiera ponowne wykorzystanie kodu i ułatwia jego utrzymanie.
Polimorfizm:
Polimorfizm pozwala używać jednolitego interfejsu do pracy z obiektami różnych klas. To osiąga się poprzez nadpisywanie metod w klasach dziedziczących, które są dziedziczone od rodzica.
Abstrakcja:
Abstrakcja polega na wyodrębnianiu wspólnych cech obiektów i tworzeniu klas, które reprezentują te wspólne cechy. To pomaga uprościć skomplikowane systemy i poprawić ich zrozumienie.
Jeśli zrozumiałeś choćby połowę – świetnie. Dalej omówimy każdy z tych punktów bardziej szczegółowo.
2.2 Abstrakcja
Dobrym przykładem abstrakcji w prawdziwym życiu jest opis stanowisk w firmie lub organizacji. Nazwa stanowiska — to jedno, a obowiązki każdej konkretnej roli — to całkiem co innego.
Wyobraź sobie, że projektujesz strukturę swojej przyszłej firmy. Możesz rozdzielić obowiązki sekretarza, „rozrzucając” je między innymi stanowiskami. Możesz podzielić stanowisko dyrektora wykonawczego na kilka niezależnych ról: dyrektora finansowego, dyrektora technicznego, dyrektora marketingu, dyrektora personalnego. Albo, na przykład, połączyć stanowiska office managera i rekrutera w jedno.
Z punktu widzenia programowania abstrakcja — to, powiedzmy, właściwy podział programu na obiekty. Zwykle każdy duży program można w dziesiątkach sposobów przedstawić jako interagujące obiekty. Abstrakcja pozwala wybrać najważniejsze cechy i pominąć drugorzędne.

Abstrakcja — to jak strategia w wojskowości. Zła strategia — i żadną genialną taktyką sytuacji już nie naprawisz.
2.3 Enkapsulacja
Celem enkapsulacji jest poprawa jakości interakcji elementów poprzez uproszczenie ich współpracy.

A najlepszy sposób na uproszczenie czegoś — to ukrycie całej złożoności przed niepożądanymi oczami. Na przykład, jeśli zostaniesz posadzony w kabinie Boeinga, nie od razu zrozumiesz, jak nim sterować:

Z drugiej strony, dla pasażerów samolotu wszystko wydaje się prostsze: kup bilet, wsiądź do samolotu, wystartuj i wyląduj. Możesz z łatwością przelecieć z kontynentu na kontynent, posiadając tylko umiejętności „kupić bilet” i „wsiąść do samolotu”. Wszystkie trudności związane z przygotowaniem samolotu do lotu, startem, lądowaniem i różnymi sytuacjami awaryjnymi są ukryte przed nami. Nie mówiąc już o nawigacji satelitarnej, autopilocie i centrach dyspozycyjnych na lotniskach. I to upraszcza nam życie.
Z punktu widzenia programowania, enkapsulacja — to „ukrycie implementacji”
. Podoba mi się ta definicja. Nasza klasa może zawierać setki metod i realizować bardzo złożone zachowanie w różnych sytuacjach. Ale możemy ukryć przed niepożądanymi oczami wszystkie jej metody (opatrzyć ich nazwy „__” z obu stron), a do interakcji z innymi klasami pozostawić tylko kilka metod. Wtedy wszystkie pozostałe klasy naszego programu będą widziały w tej klasie tylko te kilka metod i będą wywoływały właśnie je
. A wszystkie złożoności będą ukryte wewnątrz klasy, jak kabina pilotów przed szczęśliwymi pasażerami.
2.4 Dziedziczenie
Dziedziczenie ma dwie strony. Strona programowania i strona rzeczywistości. Z punktu widzenia programowania dziedziczenie — to specjalny związek między dwoma klasami
. Ale znacznie ciekawsze jest, czym jest dziedziczenie z punktu widzenia rzeczywistości.
Jeśli musielibyśmy coś stworzyć w rzeczywistości, mamy dwa podejścia:
- stworzyć potrzebną nam rzecz od zera, marnując mnóstwo czasu i wysiłku;
- stworzyć potrzebną nam rzecz na podstawie już istniejącej.
Najbardziej optymalna strategia wygląda tak: bierzemy istniejące dobre rozwiązanie, trochę je udoskonalamy, dopasowujemy do swoich potrzeb i używamy
.
Jeśli prześledzimy historię powstania człowieka, okaże się, że od momentu powstania życia na planecie minęły miliardy lat. A jeśli wyobrazić sobie, że człowiek powstał z małpy (na podstawie małpy), to minęło zaledwie kilka milionów lat. Tworzenie od zera — zajmuje więcej czasu. Znacznie więcej
.
W programowaniu też istnieje możliwość tworzenia jednej klasy na podstawie innej. Nowa klasa staje się potomkiem (dziedzicem) już istniejącej
. To bardzo korzystne, gdy mamy klasę, która zawiera 80%–90% potrzebnych nam danych i metod. Po prostu ogłaszamy odpowiednią klasę jako rodzica naszej nowej klasy, wtedy w nowej klasie automatycznie pojawiają się wszystkie dane i metody klasy-rodzica
. Prawda, że wygodne?
2.5 Polimorfizm
Polimorfizm — to pojęcie z dziedziny programowania. Opisuje sytuację, gdy pod jednym interfejsem kryją się różne implementacje. Jeśli spróbować poszukać jego analogów w rzeczywistości, to jednym z takich analogów będzie proces prowadzenia samochodu.
Jeśli ktoś potrafi prowadzić ciężarówkę, to można go posadzić zarówno za kierownicą karetki, jak i sportowego auta. Człowiek może prowadzić auto niezależnie od tego, jakie to auto, ponieważ wszystkie mają ten sam interfejs sterowania: kierownicę, pedały i dźwignię zmiany biegów
. Wewnętrzna budowa samochodów jest różna, ale wszystkie mają ten sam interfejs sterowania.
Wracając do programowania, polimorfizm pozwala jednolicie odnosić się do obiektów różnych klas (zazwyczaj mających wspólnego przodka) – rzecz, którą trudno przecenić
. Jego wartość rośnie tym bardziej, im większy jest program.
OOP — to zasady. Wewnętrzne prawa. Każdy z nich w czymś nas ogranicza, dając w zamian wielkie korzyści, gdy program się rozrasta do dużych rozmiarów
. Cztery zasady OOP to jak cztery nogi krzesła. Usuń choć jedną, a cała konstrukcja stanie się niestabilna.
GO TO FULL VERSION