PHP/Klasy i obiekty: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
m Wycofano edycje użytkownika 192.162.63.49 (dyskusja). Autor przywróconej wersji to Kabexxxior.
Znacznik: Wycofanie zmian
Linia 1:
<div class="noprint">{{prognaw|PHP|[[../Czym jest programowanie obiektowe?/]]|[[../Konstruktory i destruktory/|Konstruktory i destruktory]]}}</div>
 
jdjdjdjdjd
 
== Klasy i obiekty ==
Linia 8 ⟶ 6:
{{Uwaga|Począwszy od tego miejsca będziemy stosować angielskie nazewnictwo w programowaniu obiektowym, gdyż jest ono podstawą wielu uznanych i powszechnie stosowanych konwencji.}}
 
=== Tworzenie klas ===
resident sleeper
W językach programowania klasy traktowane są zawsze jako rodzaj typów danych. Można powiedzieć, że klasa jest '''definicją''' lub ''szablonem'' obiektów. W PHP deklarujemy je słowem kluczowym '''class''', po którym podajemy jej unikatową nazwę. Zasady jej tworzenia są podobne, jak w przypadku nazw zmiennych, tj. nie mogą one zaczynać się od cyfry. Następnie w nawiasach klamrowych umieszczamy informacje o dozwolonych polach oraz metodach, jakie klasa będzie posiadać:
 
<source lang="php" line><?php
class Person
{
public $name;
public $surname;
public function setFullName($name, $surname)
{
$this->name = $name;
$this->surname = $surname;
} // end setFullName();
public function getFullName()
{
return $this->name.' '.$this->surname;
} // end getFullName();
}
</source>
 
Zwyczajowo pola deklaruje się na początku klasy, natomiast później - metody, które okazują się być bardzo podobne do funkcji. Podobieństwo jest jak najbardziej uzasadnione. Właściwie funkcje także reprezentują pewne zachowanie, więc nic nie stoi na przeszkodzie, aby wykorzystać tę funkcjonalność do zdefiniowania zachowań obiektów. Zasady działania metod są bardzo podobne - pobierają one argumenty i mogą zwracać wartość. Jedyna istotna różnica to obecność specjalnego wskaźnika <code>$this</code>, który wskazuje zawsze na obiekt, na którym daną metodę wywołujemy. Dzięki niemu możemy dostać się do wartości przechowywanych w polach obiektu oraz wywoływać inne metody. Służy do tego specjalny operator '''->'''. Zauważ, że odwołując się do pól, pomijamy znak dolara. Nie przejmuj się słowem kluczowym '''public'''. Jego znaczenie poznamy za chwilę.
 
Pola klasy zachowują się, jak zwykłe zmienne. Mogą być częścią wyrażeń, możemy do nich przypisywać wartości i wykonywać wszystkie inne operacje, które są prawidłowe dla zmiennych.
 
Stwórzmy teraz kilka obiektów klasy '''Person''' reprezentujących różne osoby. W przeciwieństwie do większości języków kompilowanych, a podobnie jak w Javie, obiekty nie są jednym z rodzajów wartości, ale specjalnym bytem. Wartość obiektowa to jedynie referencja do istniejącego już obiektu. Gdy wykonujemy przypisanie lub przekazujemy obiekt jako argument funkcji/metody, kopiujemy jedynie referencję, a nie obiekt. Wbrew pozorom takie zachowanie jest bardzo praktyczne. W PHP4, gdzie obiekt był jednocześnie wartością, korzystanie z programowania obiektowego było przez to bardzo problematyczne i prowadziło do wielu błędów.
 
Obiekty tworzymy operatorem '''new''', po którym podajemy nazwę klasy. Zwraca on referencję do obiektu, którą możemy zapisać w zmiennej:
 
<source lang="php" line><?php
// Dolaczamy plik z nasza klasa
require('./Person.php');
 
$janusz = new Person;
$janusz->setFullName('Janusz', 'Kowalski');
 
$adam = new Person;
$adam->setFullName('Adam', 'Nowak');
 
echo 'Witaj, jestem '.$janusz->getFullName().'<br/>';
echo 'A ja jestem '.$adam->getFullName().'<br/>';
</source>
 
Możemy też odwołać się bezpośrednio do odpowiednich pól: <code>$adam->name</code>.
 
Wywołanie metod jest niezwykle proste. Wystarczy wziąć obiekt i po operatorze '''->''' wywołać metodę dokładnie w taki sam sposób, jak to robiliśmy z funkcjami. Metody zawsze działają w imieniu tego obiektu, na którym zostały wywołane, a to prowadzi nas do jednej z kluczowych reguł projektowania obiektowego:
 
{{Definicja|Metody definiują zachowanie obiektów, dlatego powinny operować przede wszystkim na obiekcie, który je wywołał.}}
 
Do klasy '''Person''' nie będziemy dodawać metody w stylu <code>polaczSieZBazaDanych()</code>, ponieważ klasa jest definicją obiektów - przypisujemy więc właściwości i metody związane bezpośrednio z opisem człowieka. Łączenie się z bazą danych jest oddzielnym zadaniem. Co więcej, lepiej zrobić to projektując połączenie uniwersalne, na przykład w oddzielnej klasie.
 
=== Zmienne obiektowe są referencjami ===
Wspomnieliśmy, że w PHP5 obiekty nie są rodzajem wartości, lecz oddzielnym bytem, do którego skrypt posiada jedynie referencje. Spójrzmy, czym to skutkuje w praktyce. Rozpatrzmy prosty skrypt:
 
<source lang="php" line><?php
function modify($value)
{
$value += 5;
} // end modify();
 
$number = 6;
modify($number);
echo $number;
</source>
 
Skrypt ten wyświetli nam wartość "6". Zmienna, na której operuje funkcja <code>modify()</code> jest jedynie kopią zmiennej globalnej <code>$number</code>, dlatego jej modyfikacja nie wpływa na wartość oryginału. Inaczej jest w przypadku obiektów:
 
<source lang="php" line><?php
require('./Person.php');
 
function modify($object)
{
$object->surname = 'Nowak';
} // end modify();
 
$janusz = new Person;
$janusz->setFullName('Janusz', 'Kowalski');
modify($janusz);
echo $janusz->getFullName();
</source>
 
Tym razem skrypt wyświetlił nam wartość <code>Janusz Nowak</code>, co oznacza, że zmiana stanu obiektu wprowadzona przez funkcję jest widoczna globalnie. Zachowanie jest jak najbardziej prawidłowe. Funkcja <code>modify()</code> operuje nie na kopii, ale na referencji do obiektu. Obie referencje: globalna <code>$janusz</code> oraz lokalna <code>$object</code> są oddzielne, ale wskazują na dokładnie ten sam obiekt. Dlatego wykonanie operacji poprzez jedną z nich sprawi, że druga także zauważy zmiany.
 
{{Infobox|Zapamiętaj, przekazanie zmiennej obiektowej przez argument lub przypisanie jej wartości operatorem '''<nowiki>=</nowiki>''' kopiuje jedynie referencję do obiektu, a nie obiekt.}}
 
Spróbuj w ramach ćwiczenia wykonać taką samą sztuczkę z operatorem przypisania.
 
to tez spanie jest
we we starym se trzasnij haHAA
jdjd
orszul spoko ziomek
=== Kontrola dostępu (hermetyzacja) ===
W przeciwieństwie do funkcji i programowania strukturalnego, klasy posiadają precyzyjne mechanizmy kontroli dostępu do swojego wnętrza. Proces ukrywania części funkcjonalności przed programistą nosi nazwę ''hermetyzacji'' i pomaga zwiększyć niezawodność oprogramowania. Tworząc klasę, będziemy zawsze starali się określić tzw. publiczny interfejs, z którego może korzystać programista, odwołując się do tworzonych obiektów, jednocześnie ukrywając wszystkie wewnętrzne aspekty działania klasy. Interpreter będzie pilnować, aby użytkownicy nie wywołali żadnej "wewnętrznej" metody, co mogłoby doprowadzić do błędów w działaniu lub użycia jej niezgodnie z przeznaczeniem.
Linia 195 ⟶ 275:
 
Stworzony system konfiguracji wykorzystuje jeszcze jedną technikę programistyczną o nazwie '''kompozycja'''. Jest to alternatywny do dziedziczenia sposób rozszerzania funkcjonalności obiektów, który jednak nie wymaga żadnej dodatkowej składni. Obrazowo mówiąc, polega on na tym, że jeden obiekt przechowuje referencje do innych obiektów, które potrafi wykorzystywać lub których funkcjonalność potrafi udostępnić na zewnątrz. W przeciwieństwie do dziedziczenia, kompozycja ma charakter dynamiczny. Możemy napisać algorytm, który w locie skomponuje nam gotowy obiekt, niczym z klocków lego, np. na podstawie konfiguracji lub opisu w bazie danych. Kompozycja jest bardzo często stosowana w praktyce obok dziedziczenia.
 
== Zakończenie ==
Mamy już solidne podstawy programowania obiektowego, a także pokazaliśmy, w jaki sposób wykorzystuje się jego własności podczas tworzenia oskryptowania stron internetowych, pisząc modularny i łatwy w rozbudowie system konfiguracji. W następnym rozdziale pokażemy, jak sterować tworzeniem i niszczeniem obiektów.