Programowanie obiektowe określa odmienne spojrzenie na tworzenie programu. Nadal mamy do dyspozycji funkcje, zmienne, itd, ale występuje pomiędzy nimi pewna zależność. Funkcje przestają być niezależnymi tworami, a zaczynają spełniać ściśle określone role.

Świat przestaje być zbiorem luźno powiązanych ze sobą elementów, a staje się grupą obiektów o określonych właściwościach. Najprościej zademonstrować to zagadnienie można na podstawie jakiegoś ograniczonego zbioru liczb. Jak wiadomo zbiór taki można opisać szeregiem cech: liczba elementów, rodzaj elementów, itp. Możemy także przedstawić operacje jakie można wykonać na takim zbiorze, np: usunąć wskazane liczby, pomnożyć wszystkie przez jakąś liczbę lub na bazie tego zbioru utworzyć kilka podzbiorów.

Definicje i prosta klasa

Jak sama nazwa wskazuje programowanie obiektowe, to działania na obiektach. Obiektem nazywamy element utworzony na podstawie określonej definicji (klasy). Ma on właściwości (atrybuty), oraz można wykonywać na nim operacje (metody). W przypadku atrybutów mogą to być zmienne napisowe, liczby, tablice. Natomiast metody to funkcje, które wykonują zadane operacje. Wśród tych funkcji występują dwie o szczególnym znaczeniu. Pierwsza to konstruktor. Funkcja ta jest wywoływana w momencie tworzenia obiektu. W uproszczeniu można powiedzieć, że dzięki niej można ustawić początkowe wartości wskazanych zmiennych. Aby funkcja stała się konstruktorem wystarczy, żeby miała taką samą nazwę jak klasa. Druga ważna funkcja to destruktor. W php nie jest ona używana.

Pora napisać kawałek kodu, dzięki któremu będzie widać co i jak.

class Zespolone { 
  var $real; 
  var $imag; 
  
  function Zespolone( $r, $i ) { 
    $this->real = $r ; 
    $this->imag = $i ; 
  }      
  
  function Cout() { 
    echo $this->real." +j".$this->imag ; 
  } 
} 

$liczba_a = new Zespolone( 0, 1 ) ; 
$liczba_b = new Zespolone( 2, -3 ) ; 
$liczba_a->Cout() ; 
$liczba_b->Cout() ; 

Mamy zdefiniowaną klasę Zespolone, która będzie służyła do zapisu liczb zespolonych (wikipedia). Posiada ona pola $real i $imag, które przechowywać będą liczby. Ma ona także konstruktor, który inicjuje wartości atrybutów. Ostatnia funkcja będzie służyć do wyświetlania liczby zespolonej. Na koniec tworzymy w skrypcie dwie liczby zespolone 0+j1 oraz 2-j3.
W kodzie pojawiło się:

$this->real 
$this->imag 

Ten zapis powoduje, że odwołujemy się do zmiennych związanych z daną klasą ($this), a nie np. do zmiennych globalnych. Dodatkowo strzałka -> wskazuje na powiązanie pomiędzy obiektem, a zmienną lub funkcją. Oczywiście na danym obiekcie można wykonywać tylko zdefiniowane operacje, dlatego też zapis:

$liczba_a->Pokaz(); 

spowoduje pojawienie się komunikatu o błędzie w skrypcie. Błąd zniknie kiedy zdefiniowana zostanie wewnątrz klasy funkcja o nazwie Pokaz().

Dodajmy kilka metod operujących na liczbach zespolonych.

  function Set_Real( $r ) { $this->real = $r ; } 
  function Set_Imag( $i ) { $this->imag = $i ; } 

  function Get_Real() { return $this->real ; } 
  function Get_Imag() { return $this->imag ; } 

  function Add( $arg ) { 
    $this->real += $arg->Get_Real() ; 
    $this->imag += $arg->Get_Imag() ; 
  } 

Dwie pierwsze metody ustawiają poszczególne atrybuty, dwie kolejne podają wartość, ostatnia służy do dodawania do siebie dwóch liczb zespolonych. O ile ustawianie i pobieranie atrybutów nie wymaga tłumaczenia, to na funkcji Add należy skupić swoją uwagę. Przede wszystkim przyjęte zostało, że $arg to liczba zespolona (później zostanie to odpowiednio zmodyfikowane). Dane pobierane są z argumentu poprzez odpowiednie metody. Pozwala to zachować kontrolę nad kodem (uwaga, w starszych wersjach php można odwoływać się bezpośrednio do atrybutów danego obiektu, jednak może to prowadzić do błędów przy pracy zespołowej). Ostatnią rzeczą, na którą należy zwrócić uwagę jest to, że modyfikowane są atrybuty obiektu, który wywołał daną metodę.

$liczba_a->Add( $liczba_b ) ; 
$liczba_a->Cout() ; 

Po wykonaniu powyższego kodu zobaczymy na ekranie napis: 2+j(-2).

Nie zawsze jednak chcemy, żeby wywołanie metody powodowało zmianę atrybutów obiektu. Czasami przydatne jest utworzenie nowego obiektu, do którego przekazany zostanie wynik. Dodajmy zatem jeszcze jedną metodę, która będzie tworzyć nowy obiekt.

class Zespolone { 
 // ... 
function Add2( $arg ) { 
   $liczba = new Zespolone( 0, 0 ) ; 
   $liczba->Set_Real( $this->real + $arg->Get_Real()) ; 
   $liczba->Set_Imag( $this->imag + $arg->Get_Imag()) ; 
   return $liczba ; 
} 
} 
// ... 
$liczba_c = $liczba_a->Add2( $liczba_b ) ; 
$liczba_c->Cout() ; 

Najpierw tworzony jest nowy obiekt, któremu przypisywana jest wartość neutralna. Następnie ustawiane są wartości atrybutów, a na końcu następuje przekazanie uzyskanej liczby zespolonej na wyjście funkcji. Metoda Add2 wykonywana jest przez obiekt $liczba_a, dlatego też $this będzie wskazywać właśnie na nią. Wartość $this->real ma wartość 0, $arg->Get_Real() ma wartość 2, więc w rezultacie $liczba->real przyjmie wartość 2. Podobnie sprawa ma się z atrybutem imag. Ostatecznie nowy obiekt $liczba zostaje powiązany ze zmienną $liczba_c. Ostatecznie liczba_c przyjmie wartość 2-2j.

Mezzmo - filmy i muzyka z PC na TV i DLNA

Dziedziczenie i zastępowanie

To kolejne pojęcia związane z programowaniem obiektowym. Dzięki dziedziczeniu możemy tworzyć klasy potomne, które zawierać będą oprócz tych odziedziczonych także własne metody i atrybuty. Na bazie klasy Figura utworzyć można klasy Prostokąt, Trójkąt, Okrąg. Nic nie stoi na przeszkodzie, żeby uszczegółowić klasę Prostokąt i utworzyć na jej podstawie klasę Kwadrat. Natomiast dzięki zastępowaniu możemy definiować w klasach pochodnych metody o takich samych nazwach, ale o zupełnie innym działaniu. Możemy także wewnątrz metod, które zastąpiły wcześniejsze definicje, wywoływać metody z klasy nadrzędnej.

Zatem, do dzieła. Jak wiadomo, liczby zespolone mogą być także przedstawiane w postaci trygonometrycznej. Utwórzmy zatem klasę, która będzie umożliwiała zapis liczb zespolonych w jednej z dwóch postaci.

class Zespolone2 extends Zespolone { 
  var $fi; 
  var $mod; 
  
  function Zespolone2( $mod, $fi ) { 
    $this->mod = $mod ; 
    $this->fi = $fi ; 
    // wyliczenie wartosci zmiennych real oraz imag 
  }      
  
  function Cout( $sposob = "try" ) { 
    if( $sposob == "alg" ) Zespolone::Cout() ; 
    else 
      echo "|".$this->mod."|(cos".$this->fi." + sin".$this->fi.")" ; 
  } 

  function Add( $arg ) { 
    if( is_int( $arg )) { 
      $this->real += $arg ; 
    } elseif( is_object( $arg )) { 
      $this->real += $arg->Get_Real() ; 
      $this->imag += $arg->Get_Imag() ; 
    } 
    // wyliczenie nowej wartosci modulu oraz kata 
  } 
} 

$liczba_a = new Zespolone2( 10, 45 ) ; 
$liczba_b = new Zespolone2( 2, -30 ) ; 
$liczba_a->Cout() ; 
$liczba_b->Cout() ; 

Nowa klasa dziedziczy wszystkie funkcje oraz zmienne związane z klasą rodzicielską. Z tego też powodu bez problemu możemy odwoływać się do $this->real oraz $this->imag. Funkcja Cout została zastąpiona wersją, która umożliwia pokazywanie liczb na dwa sposoby. Nowy sposób to postać trygonometryczna. Stary sposób wyświetlania wywoływany jest poprzez podanie nazwy klasy oraz nazwy funkcji, tj. Zespolone::Cout(). Nazwą klasy niekoniecznie musi być nazwa klasy stojącej o jeden stopień wyżej w hierarchii. Może to być dowolna klasa, pod warunkiem że jest spokrewniona z klasą wywołującą daną metodę. Natomiast funkcja Add zmieniła się w niewielkim stopniu. Nadal dodaje do siebie dwie liczby i modyfikuje obiekt, który ją wywołał. Jednakże została ona wzbogacona w instrukcje warunkowe pozwalające dodawać do siebie liczbę zespoloną oraz liczbę całkowitą lub liczbę zespoloną. Pozwala to uniknąć konieczności tworzenia nowego obiektu, gdy do liczby 1+4j dodajemy 5. Mniej obiektów, to mniejsza ilość potrzebnej pamięci. Funkcja is_object( $arg ) informuje o tym, że dana zmienna jest obiektem. Jeśli używamy obiektów z wielu klas i chcemy mieć pewność, że dodajemy do siebie odpowiednie obiekty, to możemy zastosować dodatkowo funkcję get_class( $arg ). Funkcja ta poda nazwę klasy, na bazie której utworzony został dany obiekt. Jednakże należy zachować umiar z kontrolowaniem klas, z których pochodzą obiekty. Jeśli będziemy chcieli dodać obiekt, który nie jest liczbą zespoloną, to php poinformuje o tym stosownym komunikatem (a dokładniej informacją, że metoda Get_Real() oraz Get_Imag() nie istnieje).

Dodatkowe uwagi

W trakcie tworzenia klasy należy pamiętać o tym, żeby stanowiła ona jednolitą całość. Jeśli jest ona przeznaczona do komunikacji z bazą danych, to nie powinny się w niej znajdować funkcje pokazywania zawartości strony, czy pobierania listy plików znajdujących się w katalogu. Należy również pamiętać, że im mniej obiektów, tym lepiej. Dlatego też nie należy tworzyć klas, w których jest jedna metoda. Zysk będzie znikomy.

Oczywiście nic nie stoi na przeszkodzie, aby obiekty różnych klas gromadzić w jednym miejscu, np. w tablicy. Należy jedynie pamiętać o tym, żeby sprawdzać czy dany element tablicy jest obiektem oraz do jakiej klasy należy.