diff --git a/language/oop5.xml b/language/oop5.xml new file mode 100644 index 00000000..e91163fb --- /dev/null +++ b/language/oop5.xml @@ -0,0 +1,72 @@ + + + + Klasy i obiekty + + + Wprowadzenie + + PHP zawiera kompletny model obiektowy. + Niektóre z jego funkcjonalności to: + widoczność, + klasy i metody abstrakcyjne i + finalne, + additional metody magiczne, + interfejsy oraz + klonowanie. + + + PHP traktuje obiekty w taki sam sposób jak referencje lub uchwyty, to znaczy + każda zmienna zawiera referencję do obiektu, a nie kopię całego + obiektu. Patrz też + Obiekty i referencje + + &tip.userlandnaming; + + + &language.oop5.basic; + &language.oop5.properties; + &language.oop5.constants; + &language.oop5.autoload; + &language.oop5.decon; + &language.oop5.visibility; + &language.oop5.inheritance; + &language.oop5.paamayim-nekudotayim; + &language.oop5.static; + &language.oop5.abstract; + &language.oop5.interfaces; + &language.oop5.traits; + &language.oop5.anonymous; + &language.oop5.overloading; + &language.oop5.iterations; + &language.oop5.magic; + &language.oop5.final; + &language.oop5.cloning; + &language.oop5.object-comparison; + &language.oop5.late-static-bindings; + &language.oop5.references; + &language.oop5.serialization; + &language.oop5.variance; + &language.oop5.changelog; + + + diff --git a/language/oop5/abstract.xml b/language/oop5/abstract.xml new file mode 100644 index 00000000..e2b5f9a0 --- /dev/null +++ b/language/oop5/abstract.xml @@ -0,0 +1,144 @@ + + + + Abstrakcja klas + + + PHP oferuje klasy i metody abstrakcyjne. + Klasy zdefiniowane jako abstrakcyjne nie mogą być instancjonowane, a każda klasa która + zawiera przynajmniej jedną metodę abstrakcyjną też musi być abstrakcyjna. + Metody określone jako abstrakcyjne określają tylko sygnaturę metody, + nie mogą określać implementacji. + + + + Podczas dziedziczenia z klasy abstrakcyjnej wszystkie metody oznaczone jako abstrakcyjne w + deklaracji klasy rodzica muszą być zdefiniowane przez klasę potomną + i przestrzegać standardowych reguł + dziedziczenia and + kompatybilności sygnatur. + + + + Przykład klasy abstrakcyjnej + +getValue() . "\n"; + } +} + +class KonkretnaKlasa1 extends AbstractClass +{ + protected function getValue() { + return "KonkretnaKlasa1"; + } + + public function prefixValue($prefix) { + return "{$prefix}KonkretnaKlasa1"; + } +} + +class KonkretnaKlasa2 extends AbstractClass +{ + public function getValue() { + return "KonkretnaKlasa2"; + } + + public function prefixValue($prefix) { + return "{$prefix}KonkretnaKlasa2"; + } +} + +$class1 = new KonkretnaKlasa1; +$class1->printOut(); +echo $class1->prefixValue('FOO_') ."\n"; + +$class2 = new KonkretnaKlasa2; +$class2->printOut(); +echo $class2->prefixValue('FOO_') ."\n"; +?> +]]> + + &example.outputs; + + + + + + + Przykład klasy abstrakcyjnej + +prefixName("Pacman"), "\n"; +echo $class->prefixName("Pacwoman"), "\n"; +?> +]]> + + &example.outputs; + + + + + + diff --git a/language/oop5/anonymous.xml b/language/oop5/anonymous.xml new file mode 100644 index 00000000..70717595 --- /dev/null +++ b/language/oop5/anonymous.xml @@ -0,0 +1,197 @@ + + + + Klasy anonimowe + + + Klasy anonimowe są przydatne gdy chcemy stworzyć proste i jednorazowo używane obiekty. + + + + +setLogger(new Logger()); + +// Użycie klasy anonimowej +$util->setLogger(new class { + public function log($msg) + { + echo $msg; + } +}); +]]> + + + + + Klasy anonimowe mogą przyjmować argumenty przez konstruktor, rozszerzać inne klasy, + implementować interfejsy i korzystać z traitów, tak jak normalne klasy: + + + + +num = $num; + } + + use JakisTrait; +}); +]]> + + &example.outputs; + + + int(10) +} +]]> + + + + + Zagnieżdżenie klasy anonimowej w innej klasie nie daje jej dostępu do + metod lub właściwości, które są oznaczone jako prywatne lub protected w tej okalającej klasie. + Aby użyć właściwości lub metod protected z + klasy okalającej, klasa anonimowa + może rozszerzać klasę okalającą. Aby użyć właściwości prywatnych + klasy okalającej, należy je przekazać przez konstruktor + klasy anonimowej: + + + + +prop) extends Outer { + private $prop3; + + public function __construct($prop) + { + $this->prop3 = $prop; + } + + public function func3() + { + return $this->prop2 + $this->prop3 + $this->func1(); + } + }; + } +} + +echo (new Okalajaca)->func2()->func3(); +]]> + + &example.outputs; + + + + + + + Wszystkie obiekty utworzone z tej samej deklaracji klasy anoniomwej są instancjami + tej samej klasy. + + + + + + + &example.outputs; + + + + + + + + Zauważ, że nazwy klas anonimowych są przypisywane przez silnik PHP, jak + pokazano w poniższym przykładzie. Te nazwy są uznawane za + detal implementacyjny i nie powinno się na nich polegać. + + + + + + &example.outputs.similar; + + + + + + + diff --git a/language/oop5/autoload.xml b/language/oop5/autoload.xml new file mode 100644 index 00000000..658a9b46 --- /dev/null +++ b/language/oop5/autoload.xml @@ -0,0 +1,122 @@ + + + + Autoloading klas + + Wielu programistów tworzących aplikacje obiektowe tworzy + osobny plik PHP dla każdej z klas. Jednym z największych + problemów jest wtedy konieczność pisania długiej listy plików do dołączenia + na początku każdego skryptu (po jednym dla każdej klasy). + + + Funkcja spl_autoload_register może zarejestrować dowolną ilość + autoloaderów (funkcji ładujących), pozwalając na automatyczne ładowanie klas i interfejsów, + jeśli nie są one obecnie zdefiniowane. Rejestrując autoloader, PHP dostaje + ostatnią szansę na załadowanie klasy lub interfejsu zanim ich brak poskutkuje błędem. + + + Wszystkie konstrukcje podobne do klas również mogą korzystać z autoloadingu. W tym klasy, + interfejsy, traity i enumeracje. + + + + Przed PHP 8.0.0 możliwe było użycie funkcji __autoload + aby automatycznie ładować klasy i interfejsy. Jednak jako mniej elastyczna + alternatywa dla spl_autoload_register funkcja + __autoload została uznana za przestarzałą od PHP 7.2.0 i usunięta + w PHP 8.0.0. + + + + + spl_autoload_register można wywołać wielokrotnie aby + zarejestrować wiele autoloaderów. Jednak rzucenie wyjątku z funkcji ładującej + przerwie ten proces i nie pozwoli uruchomić się kolejnym funkcjom + ładującym. Z tego powodu rzucanie wyjątków z funkcji ładujących jest stanowczo + odradzane. + + + + + Przykład autoloadingu + + W tym przykładzie próbujemy załadować klasy MojaKlasa1 + i MojaKlasa2 z plików MojaKlasa1.php + and MojaKlasa2.php. + + + +]]> + + + + Inny przykład autoloadingu + + W tym przykładzie próbujemy załadować interfejs ITest. + + + +]]> + + + + + + &reftitle.seealso; + + + unserialize + unserialize_callback_func + unserialize_max_depth + spl_autoload_register + spl_autoload + __autoload + + + + + + + diff --git a/language/oop5/basic.xml b/language/oop5/basic.xml new file mode 100644 index 00000000..1fe063df --- /dev/null +++ b/language/oop5/basic.xml @@ -0,0 +1,839 @@ + + + + + Podstawy + + + class + + Podstawowe definicje klas zaczynają się + od słowa kluczowego class, po którym następuje nazwa klasy, + a następnie para nawiasów klamrowych, które otaczają definicje + właściwości i metod należących do klasy. + + + Nazwa klasy może być dowolną poprawną etykietą, o ile nie jest + zastrzeżonym słowem w PHP. Poprawna nazwa + klasy zaczyna się od litery lub podkreślnika, po której następuje dowolna ilość + liter, cyfr lub podkreślników. Jako wyrażenie regularne wyglądałoby + to więc następująco: + ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$. + + + Klasa może zawierać swoje + własne stałe, zmienne + (nazywane "właściwościami" lub "własnościami") oraz funkcje (nazywane "metodami"). + + + Prosta definicja klasy + +wlasciwosc; + } +} +?> +]]> + + + + Kiedy metoda jest wywołana w kontekście obiektu, dostępna + jest pseudo zmienna $this, której wartością + jest obiekt wywołujący metodę. + + + + Wywołanie niestatycznej metody statycznie rzuca błąd typu + Error. + Przed PHP 8.0.0 skutkowało to wygenerowaniem komunikatu o przestarzałej + funkcjonalności a zmienna $this byłaby niezdefiniowana. + + + Kilka przykładów pseudo zmiennej <varname>$this</varname> + +foo(); + +A::foo(); + +$b = new B(); +$b->bar(); + +B::bar(); +?> +]]> + + &example.outputs.7; + + + + &example.outputs.8; + + + + + + + + Klasy tylko do odczytu (readonly) + + Począwszy od PHP 8.2.0 klasa może być oznaczona + modyfikatorem readonly. + Oznaczenie klasy jako readonly doda + modyfikator readonly + do każdej z jej właściwości i uniemożliwi tworzenie + właściwości dynamicznych. + Ponadto nie możliwe jest włączenie ich obsługi przy użyciu + atrybutu AllowDynamicProperties. Próba zrobienia tego + poskutkuje błędem czasu kompilacji. + + + + +]]> + + + + + Jako że właściwości nieotypowane oraz statyczne nie mogą być oznaczone + modyfikatorem readonly, klasy tylko do odczytu + nie mogą ich deklarować: + + + + +]]> + + + +]]> + + + + Klasa tylko do odczytu może być + rozszerzona + wyłącznie przez klasę, która także jest + tylko do odczytu. + + + + + + new + + Aby stworzyć instancję (obiekt) klasy, należy użyć słowa kluczowego new. + Obiekt zostanie utworzony zawsze, chyba że klasa ma zdefiniowany + konstruktor, który rzuca + wyjątek w wypadku błędu. Klasy + powinny być zdefiniowane przed próbą stworzenia ich obiektów (instancjonowaniem), a + w niektórych wypadkach jest to wymóg. + + + Jeżeli ze słowem kluczowym new zostanie użyta zmienna zawierająca + ciąg znaków będący nazwą klasy, to zostanie stworzony nowy obiekt tej klasy. Jeśli + klasa jest w przestrzeni nazw, to musi być użyta jej w pełni kawalifikowana nazwa + (tj. taka, która zawiera przestrzeń nazw). + + + + + Jeśli do konstruktora klasy nie są przekazywane żadne argumenty, + to nawiasy po nazwie klasy można pominąć + + + + + Tworzenie instancji (obiektu) + + +]]> + + + + Od PHP 8.0.0 dozwolone jest użycie new z dowolnymi + wyrażeniami. Pozwala do na bardziej złożone instancjonowanie, jeśli wyrażenie + tworzy typ string. Wyrażenia muszą być zamknięte w nawiasach. + + + Tworzenie obiektu z pomocą wyrażenia + + Poniżej pokazujemy różne przykłady poprawnych wyrażeń, które tworzą nazwę klasy, + w tym wywołanie funkcji, łączenie ciągów znaków oraz użycie stałej ::class. + + + +]]> + + &example.outputs.8; + + + + + + Jeśli kod jest już w kontekście klasy, to możliwe jest stworzenie + nowego obiektu używając new self oraz new parent. + + + Jeśli przypiszemy stworzoną już instancję klasy do nowej zmiennej, to nowa zmienna + będzie odnosić się do tej samej instancji, do której przypisany był obiekt. To + zachowanie jest identyczne w wypadku przekazywania instancji do funkcji. Aby + stworzyć kopię już utworzonego obiektu, należy go + sklonować. + + + Przypisanie obiektu + +var = '$przypisana będzie miała tą wartość'; + +$instancja = null; // $instancja oraz $referencja mają teraz wartość null + +var_dump($instancja); +var_dump($referencja); +var_dump($przypisana); +?> +]]> + + &example.outputs; + + + string(30) "$przypisana będzie miała tą wartość" +} +]]> + + + + Nowe obiekty można stworzyć na kilka sposobów: + + + Tworzenie nowych obiektów + + +]]> + + &example.outputs; + + + + + + + Możliwe jest uzyskanie dostępu do elementu właśnie stworzonego obiektu + w pojedynczym wyrażeniu: + + + Uzyskanie dostępu do elementu właśnie stworzonego obiektu + +format('Y'); +?> +]]> + + &example.outputs.similar; + + + + + + + + Przed PHP 7.1 argumenty nie są ewaluowane jeśli klasa nie ma metody + konstruktora. + + + + + + Właściwości i metody + + Właściwości i metody klasy żyją w osobnych "przestrzeniach nazw", więc + możliwe jest, aby mieć właściwość i metodę o tej samej nazwie. Użycie + do właściwości oraz metody korzysta z tej samej notacji i to, czy uzyskamy + dostęp do właściwości, czy wywołamy metodę, zależy wyłącznie od kontaktu, + tj. czy używamy zmiennej, czy tez wywołujemy metodę. + + + Dostęp do właściwości vs. wywołanie metody + +bar, PHP_EOL, $obj->bar(), PHP_EOL; +]]> + + &example.outputs; + + + + + + Oznacza to, że wywołanie funkcji + anonimowej, która została przypisana do właściwości nie jest + możliwe bezpośrednio. Zamiast tego należy najpierw przypisać właściwość do zmiennej. + Jest też możliwe wywołanie takiej właściwości po + otoczeniu jej nawiasami. + + + Wywołanie funkcji anonimowej przechowywanej we właściwości + +bar = function() { + return 42; + }; + } +} + +$obj = new Foo(); + +echo ($obj->bar)(), PHP_EOL; +]]> + + &example.outputs; + + + + + + + + + + extends + + Klasa może odziedziczyć stałe, metody i właściwości innej klasy przy + użyciu słowa kluczowego extends (rozszerza) w deklaracji + klasy. Nie jest możliwe rozszerzanie z wielu klas na raz, + klasa może dziedziczyć tylko z jednej klasy bazowej. + + + Dziedziczone stałe, metody i właściwości mogą być nadpisane przez + ich ponowne zdeklarowanie przy użyciu tej samej nazwy jak w klasie + rodzica. Jeśli jednak klasa rodzica zadeklarowała metodę lub stałą + jako finalną, + to nie można ich nadpisać. Można uzyskać dostęp do nadpisanych + metod i właściwości statycznych odnosząc się do nich + przy użyciu słowa kluczowego parent::. + + + + Od PHP 8.1.0 stałe mogą być zadeklarowane jako finalne. + + + + Proste dziedziczenie klas + +wyswietlWlasciwosc(); +?> +]]> + + &example.outputs; + + + + + + + Zasady zgodności sygnatur + + W wypadku nadpisania metody jej sygnatura musi być kompatybilna z metodą + rodzica. W przeciwnym wypadku pojawi się błąd krytyczny, a przed PHP 8.0.0 + ostrzeżenie (E_WARNING). + Sygnatura jest uznawana za kompatybilną jeżeli przestrzega + reguł zmienności, czyni + wymagane parametry opcjonalnymi, dodaje tylko opcjonalne parametry i + nie ogranicza, a jedynie używa mniej restrykcyjnego modyfikatora widoczności. + Te zasady są znane jako Zasada Podstawienia Liskov lub LSP. + Konstruktor + oraz metody prywatne są wyłączone z zasad zgodności sygnatur i + w wypadku niezgodnych sygnatur nie zostanie zgłoszony + żaden błąd. + + + Kompatybilne metody potomne + +foo(); +$rozszerzona2 = new Rozszerzenie2(); +$rozszerzona2->foo(1); +]]> + + &example.outputs; + + + + + + + Następujące przykłady pokazują, że klasa potomna, która usuwa parametr lub czyni parametr opcjonalny + wymaganym, nie jest kompatybilna z metodą rodzica. + + + Błąd krytyczny gdy klasa potomna usuwa parametr + + + + &example.outputs.8.similar; + + + + + + Błąd krytyczny gdy klasa potomna czyni parametr opcjonalny wymaganym + + + + &example.outputs.8.similar; + + + + + + + + Zmiana nazwy parametru w klasie potomnej nie jest niezgodnością + sygnatur. Jest to jednak niezalecane, ponieważ spowoduje to + błąd Error w trakcie uruchamiania kodu, jeśli + użyte są + nazwane argumenty. + + + Błąd w wypadku użycia nazwanych parametrów i zmiany nazwy parametru w klasie potomnej + +test(foo: "foo", bar: "bar"); // BŁĄD! +]]> + + &example.outputs.similar; + + + + + + + + + + ::class + + + Słowo kluczowe class jest używane też do + rozwiązywania nazwy klasy. + Aby uzyskać w pełni kwalifikowaną nazwę klasy NazwaKlasy + użyj NazwaKlasy::class. Jest to szczególnie przydatne dla + klas używających przestrzeni nazw. + + + + Rozwiązywanie nazwy klasy + + +]]> + + &example.outputs; + + + + + + + Rozwiązywanie nazwy klasy ::class dzieje się + w czasie kompilacji. Oznacza to, że w chwili gdy tworzony jest ciąg znaków z nazwą + klasy, autoloading jeszcze się nie odbył. W związku z tym nazwy klas są rozwiązywane + nawet jeśli klasa nie istnieje. W takim wypadku nie jest + zgłaszany żaden błąd. + + + Rozwiązywanie nazwy nieistniejącej klasy + + +]]> + + &example.outputs; + + + + + + + Począwszy od PHP 8.0.0 ::class można używać też na + obiektach. Takie rozwiązanie nazwy dzieje się w trakcie wykonywania a nie kompilacji. + Jego efekt jest identyczny, jak wywołanie get_class na obiekcie. + + + Rozwiązywanie nazwy obiektu + + +]]> + + &example.outputs; + + + + + + + Operator nullsafe dla metod i właściwości + + Począwszy od PHP 8.0.0 dostęp do metod i właściwości można uzyskać + też za pomocą operatora "nullsafe": ?->. Operator nullsafe + działa tak samo, jak normalny dostęp do właściwości lub metod, pokazany powyżej, + z tym że, jeśli obiekt, z którego pobieramy jest wartością &null; to zostanie + zwrócone &null; zamiast wystąpienia się błędu. Jeśli dostęp do obiektu jest częścią + wywołania łańcuchowego, to reszta łańcucha zostanie pominięta. + + + Skutek jest podobny do opakowania każdego dostępu w funkcję is_null, + ale jest bardziej zwięzły. + + + + Operator nullsafe + +getUser(5)?->name; + +// Działa tak samo jak poniższy blok kodu: +if (is_null($repository)) { + $result = null; +} else { + $user = $repository->getUser(5); + if (is_null($user)) { + $result = null; + } else { + $result = $user->name; + } +} +?> +]]> + + + + + + Z operatora nullsafe najlepiej korzystać wtedy, gdy null jest poprawną i potencjalnie + spodziewaną wartością właściwości lub wartością zwracaną przez metodę. Aby zaznaczyć + wystąpienie błędu, powinno się rzucić wyjątek. + + + + + + diff --git a/language/oop5/changelog.xml b/language/oop5/changelog.xml new file mode 100644 index 00000000..77b4dd30 --- /dev/null +++ b/language/oop5/changelog.xml @@ -0,0 +1,341 @@ + + + + Wykaz zmian dla modelu OOP + + Tutaj znajdziesz wykaz zmian w modelu obiektowym PHP. Opis i inne informacje na temat + tych funkcjonalności są opisane w dokumentacji modelu obiektowego. + + + + + + + &Version; + &Description; + + + + + 8.1.0 + + Dodano: wsparcie dla modyfikatora final dla stałych w klasach. Ponadto domyślnie można nadpisywać stałe zdefiniowane w interfejsach. + + + + 8.0.0 + + Dodano: wsparcie dla operatora nullsafe ?-> do dostępu do właściwości i metod na obiektach, które mogą być nullem. + + + + 7.4.0 + + Zmieniono: od teraz możliwe jest rzucenie wyjątku z wewnątrz metody + __toString. + + + + 7.4.0 + + Dodano: wsparcie dla ograniczonej kowariancji zwracanych typów oraz + kontrawariancji typów argumentów Pełna obsługa wariancji jest dostępna + tylko, jeśli użyty jest autoloading. Wewnątrz pojedynczego pliku możliwe + są tylko odwołania niecykliczne. + + + + 7.4.0 + + Dodano: można teraz określać typ dla właściwości klas. + + + + 7.3.0 + + Brak kompatybilności: odpakowywanie argumentów obiektów + Traversable z kluczami innymi niż &integer; nie jest już + obsługiwane. To zachowanie nie było zamierzone, a więc zostało usunięte. + + + + 7.3.0 + + Brak kompatybilności: w poprzednich wersjach możliwe było oddzielenie + właściwości statycznych przez przypisanie referencji. Zostało to usunięte. + + + + 7.3.0 + + Zmieniono: operator instanceof + obsługuje teraz literały jako pierwszy operand, a w takim wypadku + wynikiem jest zawsze &false;. + + + + 7.2.0 + + Przestarzałe: funkcja __autoload została uznana + za przestarzałą na rzecz spl_autoload_register. + + + + 7.2.0 + + Zmieniono: następująca nazwa nie może być już użyta jako nazwa klas, interfejsów + ani traitów: object. + + + + 7.2.0 + + Zmieniono: przy grupowej składni deklaracji use dla przestrzeni nazw + można teraz użyć przecinka na końcu listy. + + + + 7.2.0 + + Zmieniono: rozszerzanie typów parametrów. Typy parametrów z nadpisanych + metod oraz z implementacji interfejsów mogą być teraz pominięte. + + + + 7.2.0 + + Zmieniono: metody abstrakcyjne mogą teraz zostać nadpisane jeśli klasa abstrakcyjna + rozszerza inną klasę abstrakcyjną. + + + + 7.1.0 + + Zmieniono: następujące nazwy nie mogą być już użyta jako nazwy klas, interfejsów + ani traitów: void, iterable + + + + 7.1.0 + + Dodano: od teraz możliwe jest określenie + widoczności + stałych w klasach. + + + + 7.0.0 + + Przestarzałe: statyczne wywołania + metod, które nie są zadeklarowane jako statyczne. + + + + 7.0.0 + + Przestarzałe: + konstruktory w stylu PHP, tj. metody, które mają taką samą nazwę jak klasa, + w której są zdefiniowane. + + + + 7.0.0 + + Dodano: grupowane deklaracje use: klasy, funkcje + oraz stałe importowane z tej samej przestrzeni nazw mogą być teraz grupowane + razem przy użyciu jednego wyrażenia use. + + + + 7.0.0 + + Dodano: wsparcie dla + klas anonimowych + przy użyciu new class. + + + + 7.0.0 + + Brak kompatybilności: iterowanie po obiekcie innym niż Traversable + będzie działać teraz tak jak iterowanie po tablicach przekazanych przez + referencję. + + + + 7.0.0 + + Zmieniono: zdefiniowane (kompatybilnych) właściwości w dwóch użytych + traitach nie powoduje + już błędu. + + + + 5.6.0 + + Dodano: metodę __debugInfo(). + + + + 5.5.0 + + Dodano: stałą magiczną ::class. + + + + 5.5.0 + + Dodano: finally dla obsługi wyjątków. + + + + 5.4.0 + + Dodano: traity. + + + + 5.4.0 + + Zmieniono jeśli klasa abstrakcyjna + określa sygnaturę dla + konstruktora, to będzie ona teraz wymuszana. + + + + 5.3.3 + + Zmieniono: metody o takiej samej nazwie jak ostatni element + przestrzeni nazw nie są już traktowane jako konstruktory. Ta zmiana nie ma + wpływu na klasy bez przestrzeni nazw. + + + + 5.3.0 + + Zmieniono: klasy, które implementują interfejsy z metodami, które mają domyslne + wartości w prototypie nie muszą już używać wartości domyślnych takich jak + interfejs. + + + + 5.3.0 + + Zmieniono; możliwe jest teraz odniesienie się do klasy używając zmiennej (np. + echo $nazwaKlasy::STALA;). + Wartość zmiennej nie może być słowem kluczowym (np., self, + parent czy static). + + + + 5.3.0 + + Zmieniono: od teraz emitowany jest błąd E_WARNING jeśli + magiczne metody przeciążające + są zadeklarowane jako statyczne. + Wymusza to też publiczną widoczność tych metod. + + + + 5.3.0 + + Zmieniono: przed 5.3.0 wyjątki rzucone w funkcji + __autoload nie mogły być + złapane blokiem catch i + skutkowały błędem krytycznym. Od teraz wyjątki rzucone w funkcji __autoload + mogą być złapane blokiem catch pod + jednym warunkiem: jeżeli rzucany jest własny wyjątek, to klasa własnego wyjątku musi + być dostępna. Funkcja __autoload może być użyta rekurencyjnie, aby automatycznie załadować + klasę własnego wyjątku. + + + + 5.3.0 + + Dodano: metodę __callStatic. + + + + 5.3.0 + + Dodano wsparcie heredoc + oraz nowdoc + dla stałych w klasach oraz definicji właściwości. + Uwaga: wartości heredoc muszą przestrzegać takich samych reguł jak ciągi znaków w + cudzysłowie (np. brak użycia zmiennych wewnątrz nich). + + + + 5.3.0 + + Dodano: Late Static Binding. + + + + 5.3.0 + + Dodano: metodę __invoke(). + + + + 5.2.0 + + Zmieniono: metoda __toString() + była wywoływana tylko, gdy została użyta bezpośrednio z + echo lub print. + Teraz jest wywoływana w dowolnym kontekście typu &string; (np. w + funkcji printf z modyfikatorem %s), ale nie + w kontekście innych typów (np. nie z modyfikatorem %d). + Od PHP 5.2.0 konwertowanie obiektów bez metody __toString + na typ &string; wywołuje błąd o poziomie E_RECOVERABLE_ERROR. + + + + 5.1.3 + + Zmieniono: w poprzednich wersja PHP 5 użycie var + było uznane za przestarzałe i powodowało komunikat o poziomie E_STRICT. + Już nie jest uznane za przestarzałe, a więc nie wywołuje żadnych błędów. + + + + 5.1.0 + + Zmieniono metoda statyczna __set_state() + jest teraz wywoływana dla klas eksportowanych przez var_export. + + + + 5.1.0 + + Dodano: metody __isset() + i __unset() methods. + + + + + + + + + diff --git a/language/oop5/cloning.xml b/language/oop5/cloning.xml new file mode 100644 index 00000000..fea01271 --- /dev/null +++ b/language/oop5/cloning.xml @@ -0,0 +1,178 @@ + + + + Klonowanie obiektów + + + Tworzenie kopii obiektu z w pełni odzwierciedlonymi właściwościami nie + zawsze jest pożądanym zachowaniem. Dobrym przykładem potrzeby skopiowania + konstruktorów jest obiekt okna GTK, który + przechowuje zasób tego okna GTK. Gdy stworzymy duplikat tego obiektu, + to możemy chcieć stworzyć nowe okno o takich samych właściwościach, + więc nowy obiekt powinien przechowywać zasób nowego okna. Innym przykładem jest + obiekt przechowujący referencję do innego obiektu, z którego korzysta. Gdy + tworzysz replikę tego obiektu rodzica, prawdopodobnie potrzebna byłaby nowa instancja + tego drugiego obiektu, w taki sposób, aby replika miała swoją własną kopię. + + + + Kopię obiektu tworzy się przy pomocy słowa kluczowego clone + (która wywołuje metodę __clone() na + obiekcie, jeśli to możliwe) + + + + + + + + + + Podczas klonowania obiektu PHP wykona powierzchowną kopię wszystkich + właściwości obiektu. Właściwości, które są referencjami do innych zmiennych + pozostaną referencjami. + + + + void__clone + + + + + Po sklonowaniu obiektu, jeżeli dostępna jest metoda __clone(), + to zostanie wywołana ona na nowym obiekcie, tak by + pozwolić na zmianę wszystkich koniecznych właściwości. + + + + Klonowanie obiektu + +instancja = ++self::$instancje; + } + + public function __clone() { + $this->instancja = ++self::$instancje; + } +} + +class KlonowalnaKlasa +{ + public $obiekt1; + public $obiekt2; + + function __clone() + { + // Wymuś kopię this->obiekt, w przeciwnym razie + // będzie wskazywać na ten sam obiekt. + $this->obiekt1 = clone $this->obiekt1; + } +} + +$obj = new KlonowalnaKlasa(); + +$obj->obiekt1 = new PodObiekt(); +$obj->obiekt2 = new PodObiekt(); + +$obj2 = clone $obj; + + +print "Oryginalny obiekt:\n"; +print_r($obj); + +print "Sklonowany obiekt:\n"; +print_r($obj2); + +?> +]]> + + &example.outputs; + + PodObiekt Object + ( + [instancja] => 1 + ) + + [obiekt2] => PodObiekt Object + ( + [instancja] => 2 + ) + +) +Sklonowany obiekt: +KlonowalnaKlasa Object +( + [obiekt1] => PodObiekt Object + ( + [instancja] => 3 + ) + + [obiekt2] => PodObiekt Object + ( + [instancja] => 2 + ) + +) +]]> + + + + + + + Możliwy jest dostęp do właściwości właśnie sklonowanej klasy + przy użyciu pojedynczego wyrażenia: + + + Dostęp do pola właśnie sklonowanego obiektu + +format('Y'); +?> +]]> + + &example.outputs.similar; + + + + + + + + diff --git a/language/oop5/constants.xml b/language/oop5/constants.xml new file mode 100644 index 00000000..47ac7752 --- /dev/null +++ b/language/oop5/constants.xml @@ -0,0 +1,143 @@ + + + + Stałe w klasach + + Istnieje możliwość zdefiniowania stałych + dla konkretnej klasy, które pozostają niezmienialne. + Domyślna widoczność stałych w klasach to public. + + + + Klasy w stałych mogą być zredefiniowane przez klasy potomne. + Począwszy od PHP 8.1.0, klasy w stałych nie mogą być zredefiniowane przez klasy potomne, + jeśli zostały zdefiniowane z modyfikatorem final. + + + + Interfejsy też mogą definiować stałe. Zapoznaj się + z dokumentacją interfejsów, + aby zobaczyć przykłady. + + + Możliwe jest odniesienie się do stałej przy użyciu zmiennej. + Wartość zmiennej nie może być słowem kluczowym (np. self, + parent czy static). + + + Stałe w klasach są alokowane raz na klasę, a nie raz dla każdej + z instancji klasy. + + + Ustawienie i użycie stałej + +showConstant(); + +echo $class::CONSTANT."\n"; +?> +]]> + + + + Specjalna stała ::class pozwala + na rozwiązanie w pełni kwalifikowanej nazwy klasy w trakcie kompilacji, + co przydaje się szczególnie dla klas w przestrzeniach nazw: + + + Użycie ::class z klasami w przestrzeniach nazw + + +]]> + + + + + Wyrażenia w stałych klasowych + + +]]> + + + + + Modyfikatory widoczności dla stałych klasach, od PHP 7.1.0 + + +]]> + + &example.outputs.71; + + + + + + + Od PHP 7.1.0 dla stałych klasach dozwolone są modyfikatory widoczności. + + + + diff --git a/language/oop5/references.xml b/language/oop5/references.xml new file mode 100644 index 00000000..7e6d2839 --- /dev/null +++ b/language/oop5/references.xml @@ -0,0 +1,87 @@ + + + + Obiekty i referencje + + Jedną z często wspominanych zasad programowania zorientowanego obiektowo w PHP jest to, + że "obiekty są zawsze domyślnie przekazywane przez referencję". Nie jest to do końca prawda. + Ten rozdział koryguje to ogólne stwierdzenie z pomocą kilku przykładów. + + + + Referencja w PHP działa jak alias, który pozwala dwóm różnym zmiennym zapisywać + tę samą wartość. W PHP zmienna obiektu nie zawiera samego obiektu + jako wartości. Zawiera tylko identyfikator obiektu, który pozwala + kodowi używającemu obiektu na jego faktyczne znalezienie. Gdy obiekt jest przekazywany jako + argument, zwracany lub przypisywany do innej zmiennej, różne zmienne nie są aliasami: + one wszystkie mają kopię identyfikatora, który wskazuje na ten sam + obiekt. + + + + Referencje i obiekty + + +$b->foo = 2; +echo $a->foo."\n"; + + +$c = new A; +$d = &$c; // $c i $d są referencjami + // ($c,$d) = + +$d->foo = 2; +echo $c->foo."\n"; + + +$e = new A; + +function foo($obj) { + // ($obj) = ($e) = + $obj->foo = 2; +} + +foo($e); +echo $e->foo."\n"; + +?> +]]> + + &example.outputs; + + + + + +