wtorek, 20 września 2011

Jak programować obiektowo cz.1 - wstęp

trochę przydługi wstęp...

Jest szereg tutoriali pokazujących jak wykorzystać techniki obiektowe, jak je zastosować w kodzie, ale w większości z nich brak jednej ważnej informacji - OOP to przede wszystkim obiektowe myślenie. Techniki i sposób ich implementacji w danym języku programowania są jak język mówiony i gramatyka, są czymś zmiennym. Natomiast sposób myślenia obiektowego, umiejętność podejmowania decyzji w kwestiach relacji między klasami jest czymś stałym. Nie ważne, czy piszesz kod w PHP, Javie, C++ itp., ponieważ, jeżeli potrafisz poprawnie zaprojektować strukturę, to będzie ona uniwersalna, zmieni się jedynie sposób przetłumaczenia tego na język zrozumiały dla interpretera/kompilatora.

A więc o czym to będzie?
Właściwie to o tym samym, co wszędzie, czyli podstawy takie, jak: dziedziczenie, interfejsy, abstrakcje, hermetyzacja itd. Z tym, że oprócz przykładu użycia postaram się jeszcze przedstawić tok myślenia, który się za tym kryje. Tak, więc np. w dziedziczeniu nie chodzi tylko o to, że mamy dwie klasy Samochód i Samolot, które dziedziczą po abstrakcyjnej klasie Pojazd:)
Postaram się zaprezentować przykłady, kiedy dane rozwiązanie jest niekoniecznie dobre lub całkiem złe.
Tak naprawdę najwięcej będzie o myśleniu, bo w gruncie rzeczy do tego OOP się sprowadza. Ostatnim etapem dobrego programowania obiektowego jest pisanie kodu.

programowanie obiektowe - wtf?

Programowanie obiektowe jest to przedstawienie świata rzeczywistego i relacji w nim zachodzących, za pomocą obiektów. Najważniejszymi cechami programowania obiektowego są:
  • Abstrakcja
  • Enkapsulacja
  • Dziedziczenie
  • Polimorfizm
Wszystkie te pojęcia rozwinę w kolejnych wpisach.
Dzisiaj skupię się na kwestiach językowych, które są niezbędne do rozpoczęcia zabawy z OOP:

klasa

Klasa jest to typ zmiennej z punktu widzenia programowania, natomiast w ujęciu projektowym jest to ogólna definicja pewnej grupy powiązanych ze sobą obiektów. Klasa definiuje metody, czyli funkcjonalność, które są dostarczane przez obiekty. Poza tym definiuje również atrybuty, które są indywidualne (nie zawsze, ale do tego tematu jeszcze wrócę:) dla konkretnych obiektów. Czym jest obiekt? Jest to instancja danej klasy, czyli konkretna zmienna danego typu. Prosty przykład:
Janek, Ania, Zosia to obiekty klasy Człowiek. Każde z nich może spać, jeść, poruszać się i to są właśnie metody zdefiniowane w klasie Człowiek. Oprócz tego każdy człowiek posiada imię oraz datę urodzenia, jednak są one indywidualne dla każdego obiektu, czyli nie są bezpośrednio powiązane z klasą, a z obiektem danej klasy
A jak coś takiego napisać?
<?php
class Human
{
  private $_name;
  private $_birthDate;
  
  public function __construct($name, $birthDate) {/*...*/}
  public function eat() {/*...*/}
  public function sleep() {/*...*/}
  public function move() {/*...*/}
}

$janek = new Human('Janek', '1982-01-09');
$anna = new Human('Anna', '1950-02-19');
$zosia = new Human('Zosia', '1999-11-17');
Z informacji dotyczących klasy warto przeczytać jeszcze o operatorach widoczności.

abstrakcja i dziedziczenie

Klasa abstrakcyjna różni się od zwykłej klasy tym, że nie można utworzyć jej instancji. Może ona również dostarczać metod abstrakcyjnych, czyli metod, które zostały zadeklarowane i muszą zostać zdefiniowane w klasach potomnych. Aby to rozjaśnić rozwinę przykład z poprzedniego akapitu:
Pomimo iż Janek, Ania i Zosia są obiektami klasy Człowiek, to są pewne różnice charakterystyczne dla grup np. Ani i Zosia mogą urodzić dziecko, ponieważ są Kobietami, natomiast Janek nie doświadczy tego przywileju gdyż jest Mężczyzną. Dodatkowo różni ich też sposób sikania, pomimo tego, że i Kobiety i Mężczyźni to robią. Więc tak naprawdę żadne z nich nie jest tylko Człowiekiem, ale jest albo Kobietą, albo Mężczyzną
i kod:
<?php
abstract class Human
{
  private $_name;
  private $_birthDate;
  
  public function __construct($name, $birthDate) {/*...*/}
  public function eat() {/*...*/}
  public function sleep() {/*...*/}
  public function move() {/*...*/}
  abstract public function pee();
}

class Woman extends Human
{
   public function bornChild() {/*...*/}
   public function pee() {/*...*/}
}

class Man extends Human
{
   public function pee() {/*...*/}
}

$janek = new Man('Janek', '1982-01-09');
$anna = new Woman('Anna', '1950-02-19');
$zosia = new Woman('Zosia', '1999-11-17');

interfejs i realizacja

Specyficzną formą abstrakcji jest interfejs. Od klasy abstrakcyjnej odróżniają go dwie podstawowe rzeczy:
  • nie może definiować żadnych atrybutów, jedynie metody i stałe
  • wszystkie metody muszą być abstrakcyjne i publiczne
Interfejs służy do zapewnienia pewnej pożądanej funkcjonalności, bez jej implementacji.
Tak więc, gdyby Człowieka ograniczyć jedynie do sikania, to nasz kod mógłby wyglądać tak:
<?php
interface Human
{
   public function pee();
}

class Woman implements Human
{
   public function pee() {/*...*/}
}

class Man implements Human
{
   public function pee() {/*...*/}
}
Więcej o klasach abstrakcyjnych i interfejsach tutaj. Dodatkowo polecam przeczytanie artykułu o referencjach wykorzystywanych przy dziedziczeniu.

czy to wszystko?

Więcej w związku z kwestiami językowymi, które warto wykorzystać przy programowaniu obiektowym można znaleźć tutaj. Zdaję sobie również sprawę, że jest jeszcze kilka rzeczy, które warto poruszyć (np. metody/atrybuty statyczne), pominąłem je jednak celowo, ponieważ szerzej te zagadnienia poruszę w kolejnych wpisach. Również wiem, że żaden temat nie został wyczerpany w zadowalającym stopniu, ale chciałem się skupić na przedstawieniu struktur językowych, które są potrzebne do rozpoczęcia całej przygody z OOP, a nie na logice, która się za tym kryje. Do tego dojdę przy następnych wpisach:)

Proszę o komentarze, jeżeli ktoś zauważy coś niejasnego bądź błędnego. Zdaję sobie sprawę, że OOP, to na tyle trudny temat, że mogą się wkraść jakieś przekłamania.

20 komentarzy:

  1. 1. Data to dosyć skomplikowany obiekt, a nie tekst.
    2. Jak płeć (kobieta) może być wyspecjalizowaną formą gatunku (człowiek)? Błędnie użyte dziedziczenie.
    3. Przykłady w stylu "klasa Człowiek" są dla PHP kompletnie nietrafione.
    4. Piszesz niby coś o rozumowaniu obiektowym po czym ograniczasz się do wyjątkowo pobieżnego przedstawienia struktur języka.

    Słaby ten artykuł. Początkującym kompletnie nic nie wyjaśni, co najwyżej kilku złych praktyk nauczy.

    OdpowiedzUsuń
  2. no jak to, implementacja metody pee dla faceta i kobiety są zdecydowanie inne;-)

    OdpowiedzUsuń
  3. @Crozin
    Ad 4) I właśnie taki był zamiar, o czym z resztą napisałem, chciałem przedstawić strukturę języka, bo na czymś trzeba opierać przykłady.
    Ad 1) To już zależy od potrzeb użycia, więc w tym wypadku string jest wystarczający.
    Ad 2) Dlaczego błędnie? Człowiek bez określonej płci nie ma racji bytu (abstract), dopiero Kobieta/Mężczyzna (też Człowiek) jest czymś pełnym (class).
    Ad 3) Nie rozumiem? Przykład jak przykład:)

    Czy początkującym nic nie wyjaśnia? No cóż, to wstęp, ma dać bazę wiedzy, czyli info nt. struktury języka i chyba pod tym względem jest ok.
    Mam nadzieję jednak, że następne uznasz za bardziej wartościowe:)

    PS Jakie złe praktyki, bo to mnie nurtuje najbardziej, a z chęcią zmienię tekst, jeżeli są błędy merytoryczne.

    OdpowiedzUsuń
  4. Normalizacja, generalizacja - chyba nie wiesz czym jest.

    Kobieta/mężczyzna to wartości atrybutu "płeć".

    Metoda Pee powinna być interfejsem.

    Przykład z człowiekiem? Trochę stare i oklepane w prawie każdej publikacji na temat teorii obiektowości (

    OdpowiedzUsuń
  5. @SebaZ
    W tym przykładzie płeć nie może być atrybutem, gdyż w takim wypadku metoda bornChild() musiałaby być zaimplementowana w klasie Human, co logicznie jest bez sensu.
    A przykład z człowiekiem? Obiecuję, że następnym razem postaram się zaprezentować jakieś bardziej wyszukane przykłady:)

    OdpowiedzUsuń
  6. Autor, poczytaj sobie to. Wydaje mi się że te teksty są bardziej dla ludzi:
    http://di.com.pl/porady/35024,0,PHP_Programowanie_obiektowe_dla_poczatkujacych.html

    http://di.com.pl/porady/36200,0,PHP_Programowanie_obiektowe_dla_poczatkujacych_-_konstruktory_destruktory_i_magia.html

    OdpowiedzUsuń
  7. a mnie artykuł się podobał, dobra robota :)

    OdpowiedzUsuń
  8. > Dlaczego błędnie? Człowiek bez określonej płci nie ma racji bytu (abstract), dopiero Kobieta/Mężczyzna (też Człowiek) jest czymś pełnym (class).

    W takim razie płeć powinna być wymaganym parametrem konstruktora człowieka. Czym jest dziedziczenie? Relacją rodzaju "jest" (ang. "is a"). Czy płeć jest człowiekiem? Raczej nie. Natomiast każdy człowiek posiada płeć - relacja rodzaju "ma" (ang. "has a").

    Generalnie obiekt Człowiek, będzie bardzo rozbudowany, a taka czynność jak sikanie powinna zostać oddelegowana do osobnego obiektu, bo składa się z całej masy różnego rodzaju akcji.

    Tutaj jeszcze raz dobrze widać dlaczego przykład z człowiekiem jest słaby. Żeby dobrze na nim odwzorować ogólne zasady trzeba przedstawić bardzo, bardzo dużo kodu.

    OdpowiedzUsuń
  9. @Crozin
    No cóż, byłbym ignorantem, gdybym nie przyznał Ci racji:)
    Postanowiłem jednak nie zmieniać przykładu we wpisie, gdyż chodziło mi tutaj o przedstawienie struktur językowych.
    Tak czy inaczej, dzięki za czujność. Ze swojej strony mogę obiecać, że następne przykłady będą staranniej dobierane:)

    OdpowiedzUsuń
  10. A mnie pomogl ten artykol zrozumiec zwiazek miedzy Realnoscia i abstrakcyjnoscia kodu programu. Dzieki. Krzysztof

    OdpowiedzUsuń
  11. Szacunek, będę czytał Twojego bloga. Pozdrawiam, Marcin :)

    OdpowiedzUsuń
    Odpowiedzi
    1. Cieszę się, że ktoś to czyta:P i mam nadzieję, że będzie tylko lepiej:)

      Usuń
  12. Fajnie i przyjemnie napisany. Jak dla początkującego.

    OdpowiedzUsuń
  13. Ja też dziękuję autorowi za ten cykl artykułów. Całkiem przyjemnie opisana spora dawka wiedzy. Zwłaszcza dziś, gdzie nikomu się już nic nie chce pisać. Jeszcze raz dzięki :)

    OdpowiedzUsuń
  14. Kawał dobrej roboty! Miejcie na uwadze, że to są tylko tylko przykłady.

    OdpowiedzUsuń
  15. Witam, po zapoznaniu sie z tym blogiem łatwiej przysjajam sobie info jak programowac obiektowo w php. Zobaczcie jak nie zrozumiale pisza autorzy ksiaze. Dobra robota i czekamy na dalsze info. Pamietaj ze zawsze znajda sie tacy co koszula w d.. przeszkadza. Pozdrawiam wszystkich normalnych.

    OdpowiedzUsuń
  16. Artykuł przydatny, jak najbardziej założenia programowania obiektowego się nie zmieniły i są uniwersalne we większości języków prog :D

    OdpowiedzUsuń
  17. Kurs programowania w Python to jak klucz do magicznej bramy kodowania. Prosty, a zarazem potężny, umożliwia wnikliwe zrozumienie programowania, otwierając drzwi do nieskończonych możliwości tworzenia oprogramowania. https://coderslab.pl/pl/python-developer

    OdpowiedzUsuń
  18. Stwórz wyjątkową obecność online dzięki naszym profesjonalnym usługom tworzenia stron internetowych. Dostosujemy projekt do Twoich potrzeb, zapewniając atrakcyjny design i efektywną funkcjonalność. Skorzystaj już dziś, aby wyróżnić się w sieci! https://aexol.com/pl/

    OdpowiedzUsuń