1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895
|
<?xml version="1.0" encoding="iso-8859-2"?>
<!-- EN-Revision: 1.30 Maintainer: leon Status: ready -->
<!-- $Revision: 1.7 $ -->
<chapter id="language.oop">
<title>Klasy i Obiekty</title>
<sect1 id="keyword.class">
<title><literal>klasa</literal></title>
<para>
Klasa jest to zbir zmiennych i funkcji operujcych na tych zmiennych.
Do definicji klasy uywana jest nastpujca skadnia:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
class Koszyk
{
var $zakupy; // Zakupy w naszym koszyku
// Dodaj $num artykuw typu $artnr do wzka
function dodaj_produkt ($artnr, $num)
{
$this->zakupy[$artnr] += $num;
}
// Usu $num artykuw typu $artnr z wzka
function usun_produkt ($artnr, $num)
{
if ($this->zakupy[$artnr] > $num) {
$this->zakupy[$artnr] -= $num;
return true;
} else {
return false;
}
}
}
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
Definiuje to klas o nazwie Koszyk, ktra zawiera tablic asocjacyjn
artykuw znajdujcych si w wzku i dwie funkcje do dodawania i usuwania
produktw z koszyka.
</para>
<caution>
<simpara>
Ponisze uwagi dotycz PHP 4.
</simpara>
<simpara>
Nazwa <literal>stdClass</literal> jest uywana wewntrznie przez Zend i
jest zarezerwowana. W PHP nie moesz zdefiniowa klasy o nazwie
<literal>stdClass</literal>.
</simpara>
<simpara>
Nazwy funkcji <literal>__sleep</literal> i <literal>__wakeup</literal>
maj magiczne znaczenie dla klas w PHP. Klasy nie mog zawiera funkcji
o tych nazwach, chyba e zgadzasz si na przypisanie do nich magicznej
funkcjonalnoci. Poniej moesz znale wicej informacji.
</simpara>
<simpara>
PHP rezerwuje wszystkie nazwy funkcji zaczynajce si od __ na funkcje
magiczne. Zalecane jest nieuywanie funkcji z nazwami zaczynajcymi si
od __ chyba e chcesz jakiej magicznej funkcjonalnoci.
</simpara>
</caution>
<note>
<simpara>
W PHP 4 dozwolone s tylko stae inicjalizatory zmiennych
<literal>var</literal>. Aby zainicjalizowa zmienne z nie-staymi
wartociami, potrzebujesz funkcj inicjalizacyjn, ktra jest wywoywana
automatycznie zaraz po utworzeniu obiektu z danej klasy. Taka funkcja
zwana jest konstruktorem (zobacz poniej).
</simpara>
<informalexample>
<programlisting role="php">
<![CDATA[
/* Nic z tego nie bdzie dziaa w PHP 4. */
class Koszyk
{
var $dzisiejsza_data = date("Y-m-d");
var $nazwa = $imie;
var $wlasciciel = 'Fred ' . 'Jones';
var $artykuly = array("VCR", "TV");
}
/* Teraz wszystko zadziala. */
class Koszyk
{
var $dzisiejsza_data;
var $nazwa;
var $wlasciciel;
var $artykuly;
function Cart()
{
$this->dzisiejsza_data = date("Y-m-d");
$this->nazwa = $GLOBALS['imie'];
/* itp. . . */
}
}
]]>
</programlisting>
</informalexample>
</note>
<para>
Klasy s typami, ktre s w zasadzie tylko schematami dla waciwych
zmiennych. Zmienne podanego typu musisz stworzy korzystajc z operatora
<literal>new</literal>.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
$koszyk = new Koszyk;
$koszyk->dodaj_produkt("10", 1);
$inny_koszyk = new Koszyk;
$inny_koszyk->dodaj_produkt("0815", 3);
]]>
</programlisting>
</informalexample>
<para>
Kod ten tworzy obiekty $koszyk i $inny_koszyk, oba klasy Koszyk. Funkcja
dodaj_produkt() obiektu $koszyk zostaje wywoana w celu dodania 1 artykuu
typu "10" do koszyka $koszyk. 4 przedmioty typu "0815" dodawane s do
koszyka $inny_koszyk.
</para>
<para>
I $koszyk i $inny_koszyk maj funkcje dodaj_produkt(), usun_produkt() i
zmienne. S to osobne funkcje i zmienne. Obiekty mog by postrzegane jako
katalogi w systemie plikw. W systemie plikw moesz mie dwa rne pliki
README.TXT, ale tylko jeli istniej w osobnych katalogach. Aby odczyta
plik, bdc w gwnym katalogu, musisz poda pen ciek do tego pliku.
Tak samo jest przy obiektach: musisz poda pen nazw funkcji, z ktrej
chcesz skorzysta. W terminologii PHP katalogiem gwnym bdzie globalna
przestrze nazw a separatorem cieki bdzie ->. W zwizku z tym nazwy
$koszyk i $inny_koszyk zawieraj zupenie inne zmienne. Zauwa, e zmienna
nazywa si $koszyk->artykuly, a nie $koszyk->$artykuly, poniewa
nazwa zmiennej moe zawiera tylko jeden znak dolara.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
// poprawnie, jeden $
$koszyk->artykuly = array("10" => 1);
// niepoprawnie, poniwa $koszyk->$artykuly zamienia si na $koszyk->""
$koszyk->$artykuly = array("10" => 1);
// poprawnie, ale moe (ale nie musi) nie by tym, co zamierzalimy:
// $koszyk->$zmienna staje si $koszyk->artykuly
$zmienna = 'artykuly';
$koszyk->$zmienna = array("10" => 1);
]]>
</programlisting>
</informalexample>
<para>
Wewntrz definicji klasy, nie wiesz pod jak nazw obiekt bdzie dostpny
dla twojego programu: w momencie pisania klasy Koszyk, nie byo wiadomo,
e obiekty bd si nazywa $koszyk lub $inny_koszyk. W zwizku z tym nie
moesz napisa $koszyk->artykuly wewntrz klasy Koszyk. Zamiast tego,
aby uzyska dostp do funkcji i zmiennych zawartych w klasie, mona uy
pseudo-zmiennej $this, ktra moe by odczytana jako 'moje wasne' lub
'biecy obiekt'. A wic '$this->artykuly[$nrart] += $liczba' moe by
odczytane jako 'dodaj $liczba do licznika $nrart z mojej wasnej tablicy
artykuly' lub 'dodaj $liczba do licznika $nrartz tablicy artykuly zawartej
w biecym obiekcie'.
</para>
</sect1>
<sect1 id="keyword.extends">
<title><literal>extends</literal></title>
<para>
Bardzo czsto zachodzi potrzeba stworzenia klasy o funkcjach i zmiennych
podobnych do ju istniejcej klasy. Zasadniczo dobrze jest stworzy
szablonow klas, ktra moe by uyta we wszystkich twoich projektach i
przystosowywa j do specyficznych potrzeb twojego projektu. Aby uatwi
ten proces, klasy mog by rozszerzeniami innych klas. Rozszerzone, lub
mwic inaczej 'dziedziczone', klasy maj wszystkie zmienne i funkcje
klasy podstawowej (nazywa si to dziedziczeniem, mimo e nikt nie
umar) oraz to co do niej dodae w definicji rozszerzenia. Nie mona
odj pewnych rzeczy z klasy podstawowej, czyli oddefiniowa istniejcych
w klasie podstawowej funkcji i zmiennych. Rozszerzona klasa jest zawsze
zalena od jednej klasy bazowej - dziedziczenie wielokrotne nie jest
obsugiwane. Klasy mona rozszerzy uywajc sowa kluczowego 'extends'.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
class Nazwany_Koszyk extends Koszyk
{
var $wlasciciel;
function ustaw_wlasciciela ($nazwa)
{
$this->wlasciciel = $nazwa;
}
}
]]>
</programlisting>
</informalexample>
<para>
Definiuje to klas Nazwany_Koszyk, ktry ma wszystkie zmienne i funkcje
klasy Koszyk plus dodatkowa zmienna $wlasciciel i dodatkowa funkcja
ustaw_wlasciciela(). Nazwany koszyk tworzy si normalnym sposobem.
Moesz teraz ustawia i pobiera nazw waciciela koszyka. Cay czas
moesz uywa zwykych funkcji koszyka dla nazwanego koszyka:
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
$nkoszyk = new Nazwany_Koszyk; // Stwrz nazwany koszyk
$nkoszyk->ustaw_wlasciciela("kris"); // Nazwij koszyk
print $nkoszyk->wlasciciel; // Wywietl waciciela koszyka
$nkoszyk->dodaj_przedmiot("10", 1); // (funkcjonalno odziedziczona z
// koszyka)
]]>
</programlisting>
</informalexample>
</sect1>
<sect1 id="language.oop.constructor">
<title><literal>Konstruktory</literal></title>
<caution>
<simpara>
Konstruktory zachowuj si inaczej w PHP 3 i w PHP 4. Semantyka PHP 4
jest mocno zalecana.
</simpara>
</caution>
<para>
Konstruktory s funkcjami klasy, ktre s automatycznie wywoywane przy
tworzeniu nowej instancji klasy korzystajc z operatora
<literal>new</literal>. W PHP 3 funkcja staje si konstruktorem kiedy ma
tak sam nazw jak klasa. W PHP 4 funkcja staje si konstruktorem, kiedy
ma tak sam nazw jak klasa, w ktrej ta funkcja zostaa zdefiniowana -
rnica jest subtelna, ale bardzo wana (zobacz poniej)
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
// Dziaa w PHP 3 i PHP 4.
class Auto_Koszyk extends Koszyk
{
function Auto_Koszyk()
{
$this->dodaj_artykul ("10", 1);
}
}
]]>
</programlisting>
</informalexample>
<para>
Ten kod definiuj klas Auto_Koszyk, ktry jest klas Koszyk pluc
konstruktor, ktry inicjalizuje wzek z jednym artykuem "10" za kadym
razem, kiedy Auto_Koszyk jest tworzony operatorem "new". Konstruktory mog
pobiera argumenty i te argumenty mog by opcjonalne, przez co s jeszcze
bardziej uyteczne. Aby w dalszym cigu mc uywa klasy bez parametrw,
wszystkie parametry konstruktora powinny sta si opcjonalne przez dodanie
domylnych wartoci.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
// Dziaa w PHP 3 i PHP 4.
class Kontruktor_Koszyk extends Koszyk
{
function Konstruktor_Koszyk($artykul = "10", $ilosc = 1)
{
$this->dodaj_artykul ($artykul, $ilosc);
}
}
// Kup te same nudne rzeczy...
$zwykly_koszyk = new Konstruktor_Koszyk;
// Czas na prawdziwe zakupy...
$inny_koszyk = new Konstruktor_Koszyk("20", 17);
]]>
</programlisting>
</informalexample>
<caution>
<simpara>
W PHP 3, dziedziczone klasy i konstruktory maj wiele ogranicze.
Ponisze przykady powinny by dokadnie przeczytane w celu zrozumienia
tych ogranicze.
</simpara>
</caution>
<informalexample>
<programlisting role="php">
<![CDATA[
class A
{
function A()
{
echo "Jestem konstruktorem klasy A.<br>\n";
}
}
class B extends A
{
function C()
{
echo "Zwyka funkcja.<br>\n";
}
}
// W PHP 3 nie zostanie wywoany aden konstruktor.
$b = new B;
]]>
</programlisting>
</informalexample>
<para>
W PHP 3 w powyszym przykadzie nie bdzie wywoany aden konstruktor.
Zasad PHP 3 jest: 'Konstruktor to funkcja o takiej samej nazwie jak
klasa'. Nazw klasy jest B, a w klasie B nie ma funkcji o nazwie B(). Nic
si nie dzieje.
</para>
<para>
Zostao to poprawione w PHP 4 przez wprowadzenie innej zasady: jeli klasa
nie ma konstruktora, uywany jest konstruktor klasy bazowej, jeli taki
istnieje. W PHP 4 powyszy przykad wywietli 'Jestem konstruktorem klasy
A.<br>'.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
class A
{
function A()
{
echo "Jestem konstruktorem klasy A.<br>\n";
}
function B()
{
echo "Jestem zwyk funkcj o nazwie B w klasie A.<br>\n";
echo "Nie jestem konstruktorem w klasie A.<br>\n";
}
}
class B extends A
{
function C()
{
echo "Jestem zwyk funkcj.<br>\n";
}
}
// Wywoa to B() jako konstruktor.
$b = new B;
]]>
</programlisting>
</informalexample>
<para>
W PHP 3, funkcja B() z klasy A niespodziewanie stanie si konstruktorem w
klasie B, pomimo e wcale nie miaa nim by. Zasad PHP 3 jest:
'Konstruktor to funkcja o takiej samej nazwie co klasa'. PHP 3 nie
obchodzi czy funkcja zostaa zdefiniowana w klasie B czy zostaa
odziedziczona.
</para>
<para>
Zostao to poprawione w PHP 4 przez modyfikacj tej zasady do:
'Konstruktor to funkcja o tej samej nazwie co klasa w ktrej zostaa
zdefiniowana'. W zwizku z tym w PHP 4 clasa B nie miaaby wasnego
konstruktora. Wywoany byby tylko konstruktor klasy bazowej, wywietlajc
'Jestem konstruktorem klasy A.<br>'.
</para>
<caution>
<simpara>
Ani PHP 3 ani PHP 4 nie wywoa automatycznie konstruktora klasy bazowej z
kontruktora klasy pochodnej. Twoim zadaniem jest propagacja wywoa
konstruktorw klas nadrzdnych, jeli to konieczne.
</simpara>
</caution>
<note>
<simpara>
Ani w PHP 3 ani w PHP 4 nie ma destruktorw. Zamiast tego moesz uy
<function>register_shutdown_function</function> aby symulowa dziaanie
destruktorw.
</simpara>
</note>
<para>
Destruktory s funkcjami, ktre s wywoywanie automatycznie kiedy obiekty
s niszczone albo przez uycie <function>unset</function> albo przez
wyjcie z zasigu. W PHP nie ma destruktorw.
</para>
</sect1>
<sect1 id="keyword.paamayim-nekudotayim"><!-- :-) -->
<title><literal>::</literal></title>
<caution>
<simpara>
Ponisze dotyczy tylko PHP 4.
</simpara>
</caution>
<para>
Czasami dobrze jest odnosi si do funkcji i zmiennych w klasie bazowej
lub odnosi si do funkcji i klas ktre nie maj jeszcze instancji. Suy
do tego operator ::.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
class A
{
function przyklad()
{
echo "Jestem orginaln funkcj A::przyklad().<br>\n";
}
}
class B extends A
{
function przyklad()
{
echo "Jestem przedefiniowan funkcj B::przyklad().<br>\n";
A::przyklad();
}
}
// nie ma obiektu klasy A.
// ponisze wywietli
// Jestem orginaln funkcj A::przyklad().<br>
A::przyklad();
// stwrz nowy obiekt klasy B.
$b = new B;
// ponisze wywietli
// Jestem przedefiniowan funkcj B::przyklad().<br>
// Jestem orginaln funkcj A::przyklad().<br>
$b->przyklad();
]]>
</programlisting>
</informalexample>
<para>
Powyszy przekad wywouje funkcj przyklad() z klasy A, ale nie tworzc
obiektu tej klasy, przez co nie moemy napisa nic w stylu $a->przyklad().
Zamiast tego moemy wywoa przyklad() jako 'funkcj klasy', czyli jako
funkcj tylko klasy, nie adnego obiektu tej klasy.
</para>
<para>
Istniej funkcje klasy, ale nie ma zmiennych klasy. Faktycznie w czasie
wykonania nie ma adnego obiektu. W zwizku z tym funkcje klasy nie mog
uywa adnych zmiennych obiektu (ale mog uywa zmiennych lokalnych i
globalnych), ani w ogle $this.
</para>
<para>
W powyszym przykadzie, klasa B przedefiniowuje funkcj przyklad().
Orginalna definicja z klasy A jest zasonita i niedostpna, chyba e
odwoasz si do konkretnej implementacji poprzez operator ::. Aby to
zrobi, napisz A::przyklad() (powiniene jednak uy parent::przyklad(),
tak jak to pokazano w nastpnej czci).
</para>
<para>
W tym kontekcie, istnieje biecy obiekt i ktry ma zmienne obiektu. W
zwizu z tym jeli funkcja jest uyta Z WEWNTRZ funkcji obiektu, moesz
uywa $this i zmiennych obiektu.
</para>
</sect1>
<sect1 id="keyword.parent">
<title><literal>parent</literal></title>
<para>
Moe si zdarzy, e bdziesz pisa kod, ktry odnosi si do funkcji i
zmiennych klasy bazowej. Jest to moliwe jeli twoja klasa pochodna jest
ucileniem lub specjalizacj klasy bazowej.
</para>
<para>
Zamiast jawnego podawania nazwy klasy bazowej w kodzie, powiniene uy
specjalnej nazwy <literal>parent</literal>, ktra odnosi si do nazwy klasy
bazowej podanej przy <literal>extends</literal> podczas deklaracji twojej
klasy. Robic to, unikasz uycia nazwy klasy bazowej w wicej ni jednym
miejscu. Jeli twoje drzewo dziedziczenia zmienioby si podczas
implementacji, zmiana bdzie wymagaa poprawki tylko w jednym miejscu -
przy sowie kluczowym <literal>extends</literal> w deklaracji klasy.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
class A
{
function przyklad()
{
echo "Jestem A::przyklad() I dostarczam podstawow funkcjonalno.<br>\n";
}
}
class B extends A
{
function przyklad()
{
echo "Jestem B::przyklad() i dostarczam dodatkow funkcjonalno.<br>\n";
parent::przyklad();
}
}
$b = new B;
// Wywoa to B::przyklad(), ktry z kolei wywoa A::przyklad().
$b->przyklad();
]]>
</programlisting>
</informalexample>
</sect1>
<sect1 id="language.oop.serialization">
<title>Serializacja obiektw - obiekty w sesjach</title>
<note>
<simpara>
W PHP 3 obiekty trac powizania midzy klasami w czasie procesu
serializacji i odserializacji. Wynikowa zmienna bdzie typu obiekt, ale
bez klasy i bez metod, a wic w zasadzie bezuyteczn (zostanie poprostu
zmienn ze mieszn skadni).
</simpara>
</note>
<caution>
<simpara>
Ponisze informacje dotycz tylko PHP 4.
</simpara>
</caution>
<para>
<function>serialize</function> zwraca string bdcy reprezentacj dowolnej
wartoci, ktra moe by przechowywana przez PHP.
<function>unserialize</function> moe uy tego stringu aby odtworzy
orginalne wartoci zmiennej. Uycie serializacji do zapisania obiektu
zachowa wszystkie zmienne z obiektu. Zapisane nie bd funkcje z obiektu, a
jedynie nazwa klasy.
</para>
<para>
Aby istniaa moliwo uycia funkcji <function>unserialize</function> do
odzyskania obiektu, musi by zdefiniowana klasa tego obiektu. Oznacza to,
e jeli obiekt $a klasy A istnieje na page1.php i zserializujesz go,
otrzymasz string, ktry odnosi si do klasy A i zawiera wartoci wszystkich
zmiennych zawartych w $a. Jeli chcesz, aby istniaa moliwo
odserializacji tego obiektu na page2.php, na page2.php musi istnie
definicja klasy A. Mona to zrobi na przykad przez przechowywanie
definicji klasy A w zewntrznym pliku includowanym przez page1.php i
page2.php.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
classa.inc:
class A
{
var $jeden = 1;
function pokaz_jeden()
{
echo $this->jeden;
}
}
page1.php:
include("classa.inc");
$a = new A;
$s = serialize($a);
// przechowaj $s gdzie, gdzie page2.php bdzie moga go znale
$fp = fopen("store", "w");
fputs($fp, $s);
fclose($fp);
page2.php:
// to jest niezbdne aby funkcja unserialize dziaaa prawidowo.
include("classa.inc");
$s = implode("", @file("store"));
$a = unserialize($s);
// teraz uyj funkcji pokaz_jeden z obiektu $a.
$a->pokaz_jeden();
]]>
</programlisting>
</informalexample>
<para>
Jeli uywasz sesji i <function>session_register</function> do rejestracji
obiektw, te obiekty s serializowane automatycznie na kocu kadej strony
PHP i odserializowane automatycznie na kadej z nastpnych stron.
Zasadniczo znaczy to, e te obiekty mog pokaza si na dowolnej z twoich
stron jeli tylko stan si czci twojej sesji.
</para>
<para>
Mocno zalecane jest includowanie definicji klas wszystkich zarejestrowanych
obiektw na wszystkich twoich stronach, nawet jeli nie uywasz tych
zmiennych na twoich stronach. Jeli tego nie zrobisz a obiekty zostan
odserializowane bez definicji klasy, powizania klasowe zostan utracone a
obiek stanie si obiektem klasy <literal>stdClass</literal> bez adnych
dostpnych funkcji, a wic bdzie cakiem bezuyteczny.
</para>
<para>
A wic jeli w powyszym przykadzie $a stanie si czci sesji przez
wywoanie <literal>session_register("a")</literal>, powiniene includowa
plik <literal>classa.inc</literal> na wszystkich stronach, nie tylko
page1.php i page2.php.
</para>
</sect1>
<sect1 id="language.oop.magic-functions">
<title>Magiczne funkcje <literal>__sleep</literal> i <literal>__wakeup</literal></title>
<para>
<function>serialize</function> sprawdza, czy twoja klasa zawiera funkcj o
magicznej nazwie <literal>__sleep</literal>. Jeli tak, ta funkcja jest
wywoywana przed kad serializacj. Moe ona czyci obiekt i powinna
zwraca tablic z nazwami wszystkich zmiennych obiektu, ktre powinny by
serializowane.
</para>
<para>
Zaoonym uyciem <literal>__sleep</literal> jest zamknicie wszystkich
pocze do baz danych, ktre obiekt moe utrzymywa, zatwierdzenie
wszystkich oczekujcych danych lub wykonanie innych podobnych czynnoci
czyszczcych. Funkcja ta jest take przydatna jeli masz bardzo due
obiekty, ktre nie musz by zachowane w caoci.
</para>
<para>
Analogicznie, <function>unserialize</function> sprawdza czy istnieje
funkcja o magicznej nazwie <literal>__wakeup</literal>. Jeli tak, funkcja
moe rekonstruowa dowolne zasoby ktre obiekt moe posiada.
</para>
<para>
Zaoonym uyciem <literal>__wakeup</literal> jest odnowienie pocze z
bazami danych, ktre mogy zostac utracone w procesie serializacji, oraz
wykonanie innych czynnoci odbudowujcych obiekt.
</para>
</sect1>
<sect1 id="language.oop.newref">
<title>Referencje wewntrz konstruktora</title>
<para>
Tworzenie referencji wewntrz konstruktora moe prowadzi do dziwnych
efektw. Ten rozdzia ma pomc w unikaniu takich problemw.
<informalexample>
<programlisting role="php">
<![CDATA[
class Foo
{
function Foo($nazwa)
{
// stworz referencje wewnatrz globalnej tablicy $globalref
global $globalref;
$globalref[] = &$this;
// ustaw nazw na przekazan warto
$this->ustawNazwe($nazwa);
// i wywietl j
$this->wyswietlNazwe();
}
function wyswietlNazwe()
{
echo "<br>",$this->nazwa;
}
function ustawNazwe($nazwa)
{
$this->nazwa = $nazwa;
}
}
]]>
</programlisting>
</informalexample>
</para>
<para>
Sprawdmy, czy jest jaka rnica pomidzy
<varname>$bar1</varname>, ktry jest tworzony przy pomocy operatora
przypisania <literal>=</literal>, a <varname>$bar2</varname>, ktry zosta
stworzony uywajc operatora referencji <literal>=&</literal>...
<informalexample>
<programlisting role="php">
<![CDATA[
$bar1 = new Foo('ustawione w konstruktorze');
$bar1->wyswietlNazwe();
$globalref[0]->wyswietlNazwe();
/* wyjcie:
ustawione w konstruktorze
ustawione w konstruktorze
ustawione w konstruktorze */
$bar2 =& new Foo('ustawione w konstruktorze');
$bar2->wyswietlNazwe();
$globalref[1]->wyswietlNazwe();
/* wyjcie:
ustawione w konstruktorze
ustawione w konstruktorze
ustawione w konstruktorze */
]]>
</programlisting>
</informalexample>
</para>
<para>
Wydaje si, e nie ma adnej rnicy, ale na prawd jest jedna, i to
bardzo istotna: <varname>$bar1</varname> i
<varname>$globalref[0]</varname> <emphasis>NIE</emphasis> s referencjami,
<emphasis>NIE</emphasis> s t sam zmienna. Dzieje si tak, poniewa
"new" nie zwraca domylnie referencji, ale kopi.
<note>
<simpara>
Zwracanie kopii zamiast referencji nie powoduje utraty wydajnoci (od
PHP 4 uywane jest zliczanie referencji). Jednake zazwyczaj lepiej jest
pracowa poprostu z kopiami zamiast referencji, poniewa tworzenie
referencji zabiera troch czasu, podczas gdy tworzenie kopii obiektw
teoretycznie w ogle nie zabiera czasu (chyba e ktra z tych zmiennych
jest du tablic lub obiektem i jedno z nich ulega zmianie, po czym tej
samej zmianie ulegaj pozostae zmienne; wtedy lepiej jest uy
referencji do zmieniania ich rwnolegle).
</simpara>
</note>
Aby udowodni to, co zostao zapisane powyej, przyjrzyjmy si poniszemu
programowi.
<informalexample>
<programlisting role="php">
<![CDATA[
// teraz zmienimy nazw. czego si spodziewasz?
// moesz si spodziewa, e i $bar1 i $globalref[0] zmieni swoje nazwy...
$bar1->ustawNazwe('ustawiona z zewntrz');
// jak napisano powyej, nic takiego si nie stanie
$bar1->wyswietlNazwe();
$globalref[0]->wyswietlNazwe();
/* wyjcie:
ustawiona z zewntrz
ustawiona w konstruktorze */
// zobaczmy co si dzieje z $bar2 i $globalref[1]
$bar2->ustawNazwe('ustawiona z zewntrz');
// na szczcie ta zmienna nie zachowuje si jak ta z poprzedniego przypadku
// s to te same zmienne, z wic $bar2->nazwa i $globalref[1]->nazwa s take
// tymi samymi zmiennymi
$bar2->wyswietlNazwe();
$globalref[1]->wyswietlNazwe();
/* wyjcie:
ustawiona z zewntrz
ustawiona z zewntrz */
]]>
</programlisting>
</informalexample>
</para>
<para>
Ustatni przykad. Postaraj si go zrozumie/
<informalexample>
<programlisting role="php">
<![CDATA[
class A
{
function A($i)
{
$this->wartosc = $i;
// domyl si dlaczego nie potrzebujemy tutaj referencji
$this->b = new B($this);
}
function stworzRef()
{
$this->c = new B($this);
}
function wyswietlWartosc()
{
echo "<br>","klasa ",get_class($this),': ',$this->value;
}
}
class B
{
function B(&$a)
{
$this->a = &$a;
}
function wyswietlWartosc()
{
echo "<br>","klasa ",get_class($this),': ',$this->a->value;
}
}
// sprbuj zrozumie dlaczego uycie tu prostego kopiowania moe powodowa
// nieporzdany efekt w linii uznaczonej znaczkiem '*'
$a =& new A(10);
$a->stworzRef();
$a->wyswietlWartosc();
$a->b->wyswietlWartosc();
$a->c->wyswietlWartosc();
$a->value = 11;
$a->wyswietlWartosc();
$a->b->wyswietlWartosc(); // *
$a->c->wyswietlWartosc();
/*
wyjcie:
klasa A: 10
klasa B: 10
klasa B: 10
klasa A: 11
klasa B: 11
klasa B: 11
*/
]]>
</programlisting>
</informalexample>
</para>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"../../manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
|