PHP OOP - Clase si Obiecte, Metoda constructor OOP

download PHP OOP - Clase si Obiecte, Metoda constructor OOP

of 24

Transcript of PHP OOP - Clase si Obiecte, Metoda constructor OOP

PHP OOP - Clase si Obiecte, Metoda constructor

PHP OOP - Clase si Obiecte, Metoda constructor

OOP(Object Oriented Programming - Programare Orientata pe obiecte) este un concept (sau tehnica) de programare care trateaza datele si functiile ca obiecte. Important la acest concept este sa fie inteleasa bine diferenta dintreClasa(Class) siObiect(Object).Inainte de a trece la lucruri practice, iata cate ceva teoretic despre OOP.

Clasaeste o structura de date compacta, care contine variabile (numite proprietati) si functii (numite metode) prin care se pot crea diferite instructiuni legate intre ele in acea structura.Obiectelesunt elementele din script create cu o clasa, si prin care se pot folosi proprietatile si metodele din acea clasa.- De exemplu, pentru a intelege mai bine, prin analogie, o Clasa poate fi asemanata cu planul /schita unei case, iar obiectul este insasi casa, si contine proprietatile (culoare, ferestre, etc.) definite in schita. Precum, folosind acelasi plan se pot construi mai multe case, asa si in OOP, folosind aceeasi clasa se pot crea unul sau mai multe obiecte prin care se aplica in script proprietatile si functiile definite in clasa.

Practic, o clasa este o "fabrica" de obiecte, prin care se creaza obiecte cu aceeasi structura, avand proprietati si metode identice. Fiecare astfel de obiect creat poarta denumirea deInstanta a clasei.

In OOP (Programarea Orientata pe Obiect) apar termenii: "Encapsulation" (Encapsulare), "Inheritance" (Mostenire) si "Polymorphism" (polimorfism.). - Encapsularea reprezinta faptul de a utiliza proprietatile si metodele clasei fara a fi necesara cunoasterea sructurii ei. Astfel, cine foloseste o clasa intr-un script nu are nevoie sa cunoasca structura codului si instructiunilor din ea. - Mostenirea e abilitatea unei clase de a folosi proprietati si functii definite in alta clasa din care este extinsa (denumitaparinte). - Polimorfismul e abilitatea unei clase de a face mai multe lucruri, diferite, sau de a utiliza o clasa sau alta pentru a realiza lucrul dorit, avand functii similare.De exemplu, o rigla poate fi utilizata pentru a trasa linii dar si pt. a masura ceva, iar pentru a trasa linii se poate folosi si alta rigla dreapta. Acesta e polimorfism.Pentru cine este obijnuit cu modul de creare a claselor in PHP 4, incepand de la versiunea PHP 5 sunt unele schimbari de sintaxa:- Proprietatile nu se mai declara cuvar- Metoda Constructor se defineste cu numele__construct1. Creare clasa

Definirea unei clase incepe cu un cuvantul cheie "class", urmat de numele clasei si corpul ei (cuprins intre acolade). In corpul clasei se definesc proprietatile si metodele ei. - Proprietatile sunt variabile definite in interiorul clasei. - Metodele sunt functii create in interiorul clasei.Structura general de alcatuire a unei clase este urmatoarea:

class nume_clasa { $proprietate; function metoda() { // Codul functiei }}

Pentru a construi o clasa profesionala, cu elemente incluse in PHP 5+, sunt necesare si alte lucruri care trebuie adaugate.- La definirea unei clasei si a elementelor din ea (proprietati, metode) se pot aplica unele atribute speciale prin care se defineste domeniul lor de lucru (de existenta). Acest atribut se adauga inaintea variabilei sau a cuvantuluifunctions, si poate fi unul din cuvintele: public- valabil in tot scriptul

private- valabil doar in interiorul acelei clase

protected- valabil doar in acea clasa si sub-clasele extinse din ea

- Daca nu e adaugat nici un atribut, se considera "public".Astfel, formula completa pentru crearea unei clase este: class Nume_Clasa { atribut $proprietate1; atribut $proprietate2; ................. atribut function metoda1() { // Codul functiei } atribut function metoda2() { // Codul functiei }.................}- Pentru o mai buna organizare, este indicata crearea fiecarei clase intr-un fisier PHP separat si cu o denumire de forma "class.Nume_Clasa.php". Acest lucru nu e obligatorriu, doar ca indicatie; clasa poate fi creata si in scriptul unde e folosita.

Iata un exemplu de clasa simpla, ce contine doua proprietati, prima cu atributpublic(denumita $site), a douaprivate(denumita $categorie) si o metoda cu atributpublic(cu numele "pagini").Exemplu SiteClas

- Aceasta este clasa "SiteClas", pentru a-o putea folosi in orice script, sa o salvam intr-un fisier separat, denumit "class.SiteClas.php".- Formula "$this->site" indica /face sa fie apelata proprietatea "site" a obiectului curent din aceasta clasa (termenul$this(acesta, aceasta) indica precis ca se face referire la proprietatea respectiva, din instanta curenta).Cand se acceseaza proprietati se foloseste un singur caracter $. Sintaxa este$obj->proprietate, desi variabila e definita "$proprietate".

2. Utilizare clasa

Dupa ce o clasa e creata, pentru a putea fi utilizata trebuie creata o instanta de obiect a clasei. Aceasta instanta se declara in scriptul PHP, cu formula: $nume_obiect = new Nume_Clasa();- "nume_obiect" este numele obiectului prin care pot fi utilizate proprietatile si metodele acelei clase.

Iata cum poate fi utilizata clasa "SiteClas" prezentata mai sus (pt. explicatii, studiati si comentariile din cod).

- Lainclude()trebuie adaugata calea si numele fisierului cu clasa, in raport cu scriptul curent (aici sunt in acelasi director).- Inainte de a putea utiliza proprietati si metode din clasa, trebuie creata o instanta de obiect, deoarece prin aceasta se apeleaza aceste elemente, dupa sintaxa: $obiect->element- Prin apelarea metodei "pagini()" ($objSite->pagini('oop-clase-obiecte.html');) se va executa codul functiei "pagini()" definita in clasa, care afiseaza intr-un sir o adresa URL compusa din valorile proprietatilor si argumentul primit.- Observati ca valoarea proprietatilor poate fi modificata in cadrul scriptului. Proprietatea "site" poate fi apelata atat pentru a fi utilizata /afisata valoarea ei cat si pentru adaugarea altei valori (aici sirul 'www.alt-site.net/').- In browser va afisa:www.marplo.net/www.marplo.net/php-mysq/oop-clase-obiecte.htmlwww.alt-site.net/php-mysq/oop-clase-obiecte.html

Daca se incearca apelarea proprietatii private (aici "categorie"), de ex.:echo $objSite->categorie;, va determina o eroare ca cea de jos. Aceasta proprietate fiind declarataprivatepoate fi utilizata doar in codul din interiorul clasei.Fatal error: Cannot access private property SiteClas::$categorie in E:\server\www\index.php on line 15

Valoarea data unei proprietati definita in clasa poate fi de orice tip: sir (string), numar, Array sau Object.

3. Metoda constructor

Metoda constructore un tip special de functie din interiorul Clasei. Se declara cu numele__construct(doua caractere "_" in fata). Aceasta metoda este mereu "public" chiar daca nu se mentioneaza special atributul "public". Diferenta fata de celelalte functii este aceea ca Metoda Constructor e apelata automat cand se creaza o instanta la clasa respectiva, codul din ea se executa in momentul cand e creat obiectul (cunew).

Iata o noua versiune a clasei "SiteClas", care include si metoda constructor, plus o metoda cu atributprotected.

- Deoarece Metoda Constructor preia un parametri ($nume) [se pot adauga mai multi, ca la orice functie], cand se creaza o instanta la aceasta clasa trebuie sa fie adaugat si un argument.

- Prin executia metodei "__construct()", apelarea$this->Mesaj()determina si executia metodei Mesaj(), care avand atribut "protected" poate fi apelata doar in codul din corpul clasei sau alte clase extinse din ea (despre clase extinse intr-o lectie viitoare).- Acest cod simplu va returna in fereastra urmatorul mesaj:Bine ai venit Marius pe www.marplo.net/Categoria de cursuri php-mysq/

- Fapt ce demonsreaza ca Metoda Constructor este apelata automat si se executa codul din ea cand e creata instanta de obiect.Dupa cum se arata in exemplu de sus, in metoda constructor pot fi apelate si alte metode sau proprietati definite in clasa, cu sintaxa$this->, fapt ce va face ca si acele metode sa fie executate cand e creat obiectul.- Daca se apeleaza in script (in afara clasei) o metoda "protected" sau "private" (de ex., aici:$objSite->Mesaj();) va genera eroare.

Daca metoda constructor e definita cu un anumit numar de parametri, fara valoare initiala, cand se creaza instanta de obiect, clasa trebuie sa fie apelata cu acelasi numar de argumente, altfel returneaza eroare.De ex., metoda constructor din exemplu precedent e definita cu un parametru ($nume), daca s-ar crea o instanta fara argument, de forma:$obj = new SiteClass(), va genera o eroare de genul:Missing argument 1 for SiteClas::__construct(), called in ...

Dar se pot declara parametri cu valoare deja atribuita, astfel, argumentul pentru ei devine optional.De ex., in clasa Test de mai jos, metoda constructor e definita cu parametru$nume='Tu'.

- Daca instanta e creata fara argument, metoda constructor va folosi parametru $nume cu valoarea lui prestabilita ("Tu"), iar cand e adaugat argument, preia valoarea acestuia; dupa cum arata rezultatul afisat de scriptul urmator, in care se creaza doua instante de obiect la clasa Test.

-Acest exemplu arata si faptul ca se pot crea si folosi mai multe instante de obiect la aceeasi clasa.- In browser apare:Salut TuSalut Marius

In lectia urmatoare sunt prezentate metodele accesor si _destruct().1. Metoda Accesor

Variabilele (proprietatile) create intr-o clasa pot avea de la inceput o valoare sau pot fi doar simplu declarate, urmand ca valoarea lor sa fie atribuita prin intermediul unei functii (metode). Aceasta functie e denumita genericMetoda Accessor, e la fel ca oricare alta metoda, doar ca scopul ei este de a atribui valori proprietatilor; in rest, se construieste si se apeleaza la fel ca celelalte.Ca sa vedeti cum functioneaza "metoda accessor", incercati urmatorul exemplu, in care este creata o clasa "SiteClas" cu doua proprietati ('site' si 'categorie'), ambele fara valoare, iar metoda Constructor e folosita si caaccesor, atribuie valori proprietatilor prin parametri ei.

- Cand e creata instanta de obiect la clasa, metoda constructor (care se executa automat) atribuie proprietatilor "site" si "categorie" valorile din parametri, care trebuie adaugate la crearea instantei.- Metodapagini(), cand e apelata, afiseaza o adresa URL formata din valoarea proprietatilor "site", "categorie" (atribuite prin constructor) si argumentul ei$pag.- Salvam clasa intr-un fisier denumit "class.SiteClass.php", iar pentru test, se adauga urmatorul cod intr-un fisier .php salvat in acelasi director unde e si clasa.

- Dupa executie, in browser va afisa:www.marplo.net/php-mysql/oop-clase-obiecte.html

Valoarea proprietatii "site", avand atribut "public", poate fi modificata si pe parcurs in script, cu expresia: $objSite->site = valoare;2. Accesare si modificare proprietati prin metode Accesor

Variabilele in PHP nu au un tip de date stabilit precis la declararea lor, de exemplu, o variabila poate sa contina initial ca valoare un numar, iar pe parcursul scriptului sa i-se atribuie ca valoare un sir sau un Array. Aceasta flexibilitate este folositoare, dar in unele situatii poate prezenta probleme in anumite contexte din codul unei metode.De exemplu, daca intr-o metoda se parcurg datele dintr-o proprietate de tip Array iar in script acea proprietate primeste o valoare de tip Sir, apar erori.Pentru a fi siguri ca o proprietate primeste doar tipul de date care poate fi corect utilizat, se declara caprivatesi se folosesc metode accesor pentru accesarea ei, cu functii PHP de verificare a tipului de date. Aceste functii sunt:

is_bool()-Boolean- una din valorile speciale:truesaufalse is_integer()sauis_int()-Integer- numere intregi (fara virgula)

is_float()sauis_double()-Float /Double- numere cu zecimale (cu virgula)

is_numeric()-Number- orice numar sau sir ce reprezinta un numar

is_string()-String- siruri de caractere si cuvinte

is_array()-Array- Array

is_object()-Object- Obiect

is_resource()-Resource- un identificator pentru lucru cu date din sure externe (fisier, baza de date)

is_null()-Null- Valoare NULL sau nedefinita

Iata o alta versiune a clasei TestClas. Ambele proprietati sunt declarate "private", ca sa nu fie modificate in mod direct in afara clasei. Valorile initiale le primesc la crearea instantei (prin constructor). Pentru a putea accesa si modifica proprietatea "categorie" in script, se creaza special cate o metoda accesor:getCategorie()sisetCategorie()(vedeti si explicatiile din cod).

- Prin declararea proprietatilor ca "private", se respinge accesul direct la ele in afara clasei, iar pt. proprietatea "categorie" s-a creat posibilitatea de a fi accesata si modificata valoarea ei prin metodele accesor:getCategorie()sisetcategorie($val).- InsetCategorie($val)se atribuie valoarea transmisa pt. $val la "categorie" (prin formula$this->categorie = $val;) doar daca $val e de tip Sir (String) si are cel putin un caracter; altfel, utilizand formula speciala "throw new Exception('Eroare')" returneaza un mesaj de eroare.- Pentru a testa efectul acestor metode, se executa scriptul urmator, in care e utilizata o instanta la aceasta clasa.

- In browser scriptul va afisa:php-mysqlwww.marplo.net/html/introducere.html

- "php-mysql" este valoarea initiala data proprietatii "categorie" prin crearea instantei la clasa. Dar prin modificarea ei cu$objSite->setCategorie('html');, metoda pagini() va utiliza proprietatea "categorie" cu aceasta valoare (html).3. Metoda Destructor

Metoda Destructorse creaza cu numele__destruct(doua caractere '_' la inceput). Aceasta metoda este opusul lui__construct. Daca metoda constructor e apelata automat cand se creaza o instanta de obiect la clasa, metoda Destructor se apeleaza automat cand e stearsa, cuunset(), instanta la acea clasa.Se intelege mai bine din urmatorul exemplu. Clasa Test de mai jos contine o proprietate privata, "nume", o metoda accesor "setNume()", metoda constructor si destructor.

- Ca sa testam efectul metodei__destruct, se foloseste urmatorul script (vedeti explicatiile din cod).

- Prin argumentul 'Mar' adaugat la crearea instantei, metoda constructor atribuie aceasta valoare proprietatii "nume", pe care o afiseaza in mesajul returnat.- Apelarea metodei setNume() modifica valoarea acestei proprietati, iar cand instanta de obiect e stearsa, cuunset($obj), se autoapeleaza metoda "__destruct" si determina executia codului din ea, care va afisa alt mesaj, cu proprietatea "nume" avand ultima valoare setata.- Rezultatul afisat in browser este:Bine ai venit MarCu bine Plo

Metoda destructor este utila cand se doreste executarea automata a unor ultime instructiuni cand instanta la clasa e stearsa din memorie prin apelarea functiei PHP unset().

In lectia urmatoare sunt prezentate Constante si elemente Statice in Clasele PHP.

1. Constante

Pe langa proprietati (variabile) si metode (functii), in corpul clasei pot fi definite si constante, prin cuvantulconst. Sintaxa generala este: const NUME_CONSTANTA;- Diferenta principala dintre constante si proprietati e faptul ca valoarea constantei ramane aceeasi, nu mai poate fi modificata.- La constante nu se foloseste atribut (public, private, protected), doar cuvantulconst, ele sunt recunoscute ca publice.- Constantele se acceseaza prin numele clasei si operatorul doua-puncte (::) (atat in interiorul clasei cat si in script unde e creata instanta), cu formula: Nume_Clasa::NUME_CONSTANTAPentru a se distinge mai clar proprietatile de constante, se obisnueste ca numele constantelor sa fie scris cu majuscule.

Iata un exemplu de clasa cu o constanta, si cum poate fi aceasta utilizata. Clasa Test de mai jos contine o proprietate "raza", o constanta "PI", metoda constructor si o metoda "getArea()".

- Metoda constructor verifica daca argumentul adaugat la crearea instantei este de tip numar, in caz Adevarat, atribuie acea valoare la proprietatea "raza". Altfel, returneaza eroarea definita inException().- MetodagetArea()returneaza aria cercului (formula matematica estePI*Raza2).- Pentru a testa aceasta clasa si modul de accesare a constantei, folosim urmatorul script.

- Observati cum e accesata constanta "PI", cu aceeasi formula in interiorul clasei si in script, inainte de a crea instanta la clasa. Astfel,constantele pot fi accesate si fara a crea o instanta de obiect la acea clasa.- Rezultatul afisat de acest exemplu este:3.14Aria = 19103.76

Daca se incearca modificarea valorii constantei, in clasa sau in afara ei (Clasa::CONSTANTA=alta_valoare;), va genera eroare.- In interiorul clasei, constantele pot fi accesate si prin cuvantul specialselfin loc de numele clasei: self::CONSTANTA- In afara clasei, constantele pot fi accesate si prin intermediul instantei de obiect, dar dupa crearea ei. In exemplu de mai sus, dupa declararea instantei se poate folosi si $objTest::PI;2. Proprietati si metode Statice

Pe langa atributele: "public", "private" si "protected"; prin care se defineste domeniul de acces al proprietatilor si metodelor; acestea pot fi create si castatice, astfel, vor apartine exclusiv clasei, si nu pot fi apelate prin instanta de obiect a clasei, ci direct prin ea, cu operatorul doua-puncte (::).Pentru a defini o proprietate sau metoda ca statica, se foloseste cuvantulstaticinaintea atributului, cand sunt create aceste elemente. Sintaxa generala este: static atribut $proprietate static atribut function Metoda()-atributeste unul din cuvintele:public, privatesauprotected; care stabilesc domeniul de existenta.Acesteelemente staticenu pot fi apelate prin instanta de obiect deoarece nu apartin ei, ele apartin clasei si pot fi apelate cu formula: NumeClasa::$proprietate NumeClasa::metoda()- Observati ca la proprietate, cand e statica trebuie adaugat si caracterul $ (fara caracterul '$', sintaxa "NumeClasa::proprietate" este confundata cu cea pt. constante).

In interiorul clasei, elementele statice pot fi apelate si prin cuvantul specialselfin loc de numele clasei: self::$proprietate sau self::Metoda()

Iata un exemplu din care se intelege mai bine. In clasa urmatoare, denumita "elStatic" se definesc doua proprietati statice: una cu atribut "private" (site), a doua publica (id); o metoda constructor si alta statica.

- Vedeti explicatiile din cod si modul de lucru, cum sunt accesate proprietatile si metoda statica.- Deoarece elementele statice apartin direct clasei, pentru utilizarea lor nu e nevoie de crearea unei instante la aceasta clasa. Dar se pot folosi si instante, acestea determina auto-apelarea metodei constructor, dupa cum puteti vedea in scriptul urmator, care foloseste elemente din clasa "elStatic" si o instanta la ea.

- Observati ca valoarea proprietatii statice care e publica (aici "id") poate fi schimbata in afara clasei si influenteaza dupa ea toate instructiunile in care e folosita (ca si cum ar fi modificata in clasa), inclusiv orice instanta la clasa, creata dupa modificare.- Acest exemplu va afisa in browser urmatorul rezultat:78ID = 78 - site: www.marplo.netID = 89 - site: www.php.net

- Prin crearea instantei s-a obtinut rezultatul dat de metoda constructor.

Intr-o clasa se pot folosi combinate: constante, metode si proprietati statice si generale (fara "static"), dar in corpul metodelor statice se pot utiliza doar elemente care si ele sunt statice, sau constante. Accesarea in codul dintr-o metoda statica a unei proprietati cu formula$this->proprietategenereaza eroare.

$thisface referire la instanta de obiect curenta,selfse refera la clasa curenta.

La paginaFunctii - clase si obiectesunt prezentate cateva functii PHP pentru Clase si Obiecte.

In lectia urmatoare e prezentata utilizarea mostenirii si clasele extinse.

Mostenireaeste unul din cele mai utile instrumente ale Programarii Orientate pe Obiect -OOP.Prinmostenirese intelege transmiterea proprietatilor, constanttelor si a functiilor de la o clasa la alta, intr-o structura ierarhica. Prima clasa este clasa de baza, denumita "parinte", legata de aceasta se poate crea o sub-clasa, denumita "copil"; sub-clasa 'copil' mosteneste proprietatile si metodele clasei 'parinte' (cele care sunt cu atribut "public" sau "protected"), le poate folosi in instructiunile din propriul cod si le transmite cand se creaza o instanta de obiect la ea.Precum in natura copii mostenesc genele parintilor.1. Creare clasa copil

Sub-clasa "copil" se creaza cu formula: class ClasaCopil extends ClasaParinteIata cum se aplica acest procedeu in programarea PHP OOP.In exemplu prezentat aici se construieste intai o clasa de baza, denumita Site, cu doua proprietati: una cu atribut private (site), alta cu atribut public (categorie), constructor si o metoda getPag().

- Metoda Constructor atribuie valoarea din parametru $site la proprietatea "site".- Metoda getPag() returneaza o adresa URL formata din proprietatile clasei si parametru ei.Salvam aceasta clasa intr-un fisier "class.Site.php". Aceasta clasa poate fi utilizata pentru afisarea unui sir cu o adresa URL, prin apelarea metodei getPag(). Daca vrem sa obtinem aceasta adresa intr-un tag HTML tip link () se poate crea o noua metoda, pentru alta facilitate alta metoda, si tot asa se aglomereaza codul clasei, fapt ce devine o problema in cazul unor clase mari. O alta varianta este crearea unei sub-clase extinse din aceasta. Sub-clasa (copil) are abilitatea de amosteni/utiliza toate proprietatile si metodele definite ca publice si protected in clasa de baza (parinte) ca si cum ar fi create in ea (fara sa mai fie scrise inca o data). Astfel, in clasa copil se creaza doar instructiunile cu noua functie pe care o dorim, si nici nu mai trebuie modificata clasa parinte.In continuarea acestui exemplu se creaza o alta clasa, denumita LinkSite, ca extindere a clasei Site. Ea contine doar o metoda getLink() pentru afisarea unui link.

Salvam aceasta clasa, cu denumirea "class.LinkSite.php" in acelasi director unde e salvata si clasa Site.Acum, atentie la explicatii: - Pentru a avea acces la definitiile din clasa principala Site, deoarece se afla intr-un fisier extern, o includem cuinclude(). - Cuvantul special "extends" stabileste identitatea clasei LinkSite ca fiind o extindere a clasei Site. - In metoda getLink() se folosesc proprietatea "categorie" si metoda "getPag()" din clasa parinte ca si cum ar fi fost definite in aceasta clasa. Aceste elemente pot fi accesate in clasa copil deoarece au atribut "public" (functioneaza si cu "protected"). Dar proprietatea "site", care are atribut "private" in clasa parinte, nu poate fi accesata in cea copil. - Desi aceasta clasa nu are o metoda constructor, ea mosteneste constructorul clasei parinte, astfel, cand se creaza o instanta de obiect la clasa LinkSite trebuie adaugat si un argument de tip Sir, deoarece asa e definita metoda "__construct($site)" in clasa de baza (Site).

Sa testam aceasta clasa copil, cu scriptul urmator.

- Deoarece clasa LinkSite se afla intr-un fisier PHP extern, o includem cuinclude().- La crearea instantei de obiect se adauga si argumentul necesar, un sir ('www.marplo.net'), cerut de metoda constructor a clasei de baza, care e si ea mostenita.- Observati cum sunt accesate proprietatea "categorie" si metoda "getPag()" (care se afla in clasa parinte), prin instanta de obiect la clasa copil (LinkSite) ca si cum ar fi create in ea. Acesta este efectul mostenirii, atat de util in OOP.In browser va afisa urmatorul rezultat:Linkwww.marplo.net/ajax/introducere.html

2. Redefinire metode

In exemplu de mai sus, clasa copil LinkSite a mostenit si metoda "__construct()" din clasa parinte Site, fapt ce determina executarea codului din acel Constructor si cand e creata instanta la clasa copil. Uneori aceasta functie nu e adecvata in sub-clasa. Pentru a evita acest lucru, metodele inadecvate pot fi rescrise prin adaugarea uneia cu acelasi nume in clasa copil, astfel, la crearea instantei, va fi utilizata metoda, cu acelasi nume, din clasa copil.- Rescrierea unei metode nu afecteaza cu nimic pe cea originala, modificarile efectuate sunt valabile doar in clasa copil in care se face rescrierea, respectiv, in alte sub-clase ale ei.

Iata o alta sub-clasa (PagSite) extinsa din Site. Aici se adauga si o metoda "__construct()" care o va anula pe cea din clasa parinte, se rescrie si metoda getPag().

- Prin crearea in aceasta sub-clasa a metodei "__construct()" se anuleaza efectul celei din clasa parinte, si neavand parametru, nici la creare instantei nu se mai adauga vreun argument.- Pentru a pastra si functionalitatea initiala (din clasa parinte) a metodei rescrise, in corpul functie care face rescrierea, se adauga cu formulaparent::nume_metoda()(tehnica folosita si in exemplu de sus, la getPag()).In scriptul urmator se foloseste aceasta a doua sub-clasa.

- Instructiunea$objPag->getPag('introducere.html')apeleaza metoda "getPag()" din clasa la care s-a creat instanta de obiect (PagSite) deoarece exista cu aceasta denumire in ea. Se observa si din rezultatul afisat:Pagina: marplo.net/html/introducere.html

3. Metode finale

In exemplu prezentat mai sus se vede cum o metoda din clasa de baza poate fi rescrisa in sub-clasa copil, dandu-i alta functionalitate. Sunt situatii in care nu se doreste ca o metoda sa poata fi rescrisa, in acest caz, prin adaugarea cuvantuluifinalla inceputul declararii metodei se blocheaaaza posibilitatea rescrierii ei.- De exemplu:

- Va genera eroarea:Fatal error: Cannot override final method Baza::numeMet() in ...

- Deoarece metoda "numeMet()" este declarata cu atribut "final".4. Clase finale

Precum metodele declarate cu "final" nu mai pot fi modificate in sub-clasa copil, asa se pot crea si clase care sa ramana fixe, fara sa se poata crea din ele alta sub-clasa. Acest lucru se obtine prin adaugarea cuvantuluifinalinainte declass.- De exemplu:

Mostenireaeste unul din cele mai utile instrumente ale Programarii Orientate pe Obiect -OOP.Prinmostenirese intelege transmiterea proprietatilor, constanttelor si a functiilor de la o clasa la alta, intr-o structura ierarhica. Prima clasa este clasa de baza, denumita "parinte", legata de aceasta se poate crea o sub-clasa, denumita "copil"; sub-clasa 'copil' mosteneste proprietatile si metodele clasei 'parinte' (cele care sunt cu atribut "public" sau "protected"), le poate folosi in instructiunile din propriul cod si le transmite cand se creaza o instanta de obiect la ea.Precum in natura copii mostenesc genele parintilor.1. Creare clasa copil

Sub-clasa "copil" se creaza cu formula: class ClasaCopil extends ClasaParinteIata cum se aplica acest procedeu in programarea PHP OOP.In exemplu prezentat aici se construieste intai o clasa de baza, denumita Site, cu doua proprietati: una cu atribut private (site), alta cu atribut public (categorie), constructor si o metoda getPag().

- Metoda Constructor atribuie valoarea din parametru $site la proprietatea "site".- Metoda getPag() returneaza o adresa URL formata din proprietatile clasei si parametru ei.Salvam aceasta clasa intr-un fisier "class.Site.php". Aceasta clasa poate fi utilizata pentru afisarea unui sir cu o adresa URL, prin apelarea metodei getPag(). Daca vrem sa obtinem aceasta adresa intr-un tag HTML tip link () se poate crea o noua metoda, pentru alta facilitate alta metoda, si tot asa se aglomereaza codul clasei, fapt ce devine o problema in cazul unor clase mari. O alta varianta este crearea unei sub-clase extinse din aceasta. Sub-clasa (copil) are abilitatea de amosteni/utiliza toate proprietatile si metodele definite ca publice si protected in clasa de baza (parinte) ca si cum ar fi create in ea (fara sa mai fie scrise inca o data). Astfel, in clasa copil se creaza doar instructiunile cu noua functie pe care o dorim, si nici nu mai trebuie modificata clasa parinte.In continuarea acestui exemplu se creaza o alta clasa, denumita LinkSite, ca extindere a clasei Site. Ea contine doar o metoda getLink() pentru afisarea unui link.

Salvam aceasta clasa, cu denumirea "class.LinkSite.php" in acelasi director unde e salvata si clasa Site.Acum, atentie la explicatii: - Pentru a avea acces la definitiile din clasa principala Site, deoarece se afla intr-un fisier extern, o includem cuinclude(). - Cuvantul special "extends" stabileste identitatea clasei LinkSite ca fiind o extindere a clasei Site. - In metoda getLink() se folosesc proprietatea "categorie" si metoda "getPag()" din clasa parinte ca si cum ar fi fost definite in aceasta clasa. Aceste elemente pot fi accesate in clasa copil deoarece au atribut "public" (functioneaza si cu "protected"). Dar proprietatea "site", care are atribut "private" in clasa parinte, nu poate fi accesata in cea copil. - Desi aceasta clasa nu are o metoda constructor, ea mosteneste constructorul clasei parinte, astfel, cand se creaza o instanta de obiect la clasa LinkSite trebuie adaugat si un argument de tip Sir, deoarece asa e definita metoda "__construct($site)" in clasa de baza (Site).

Sa testam aceasta clasa copil, cu scriptul urmator.

- Deoarece clasa LinkSite se afla intr-un fisier PHP extern, o includem cuinclude().- La crearea instantei de obiect se adauga si argumentul necesar, un sir ('www.marplo.net'), cerut de metoda constructor a clasei de baza, care e si ea mostenita.- Observati cum sunt accesate proprietatea "categorie" si metoda "getPag()" (care se afla in clasa parinte), prin instanta de obiect la clasa copil (LinkSite) ca si cum ar fi create in ea. Acesta este efectul mostenirii, atat de util in OOP.In browser va afisa urmatorul rezultat:Linkwww.marplo.net/ajax/introducere.html

2. Redefinire metode

In exemplu de mai sus, clasa copil LinkSite a mostenit si metoda "__construct()" din clasa parinte Site, fapt ce determina executarea codului din acel Constructor si cand e creata instanta la clasa copil. Uneori aceasta functie nu e adecvata in sub-clasa. Pentru a evita acest lucru, metodele inadecvate pot fi rescrise prin adaugarea uneia cu acelasi nume in clasa copil, astfel, la crearea instantei, va fi utilizata metoda, cu acelasi nume, din clasa copil.- Rescrierea unei metode nu afecteaza cu nimic pe cea originala, modificarile efectuate sunt valabile doar in clasa copil in care se face rescrierea, respectiv, in alte sub-clase ale ei.

Iata o alta sub-clasa (PagSite) extinsa din Site. Aici se adauga si o metoda "__construct()" care o va anula pe cea din clasa parinte, se rescrie si metoda getPag().

- Prin crearea in aceasta sub-clasa a metodei "__construct()" se anuleaza efectul celei din clasa parinte, si neavand parametru, nici la creare instantei nu se mai adauga vreun argument.- Pentru a pastra si functionalitatea initiala (din clasa parinte) a metodei rescrise, in corpul functie care face rescrierea, se adauga cu formulaparent::nume_metoda()(tehnica folosita si in exemplu de sus, la getPag()).In scriptul urmator se foloseste aceasta a doua sub-clasa.

- Instructiunea$objPag->getPag('introducere.html')apeleaza metoda "getPag()" din clasa la care s-a creat instanta de obiect (PagSite) deoarece exista cu aceasta denumire in ea. Se observa si din rezultatul afisat:Pagina: marplo.net/html/introducere.html

3. Metode finale

In exemplu prezentat mai sus se vede cum o metoda din clasa de baza poate fi rescrisa in sub-clasa copil, dandu-i alta functionalitate. Sunt situatii in care nu se doreste ca o metoda sa poata fi rescrisa, in acest caz, prin adaugarea cuvantuluifinalla inceputul declararii metodei se blocheaaaza posibilitatea rescrierii ei.- De exemplu:

- Va genera eroarea:Fatal error: Cannot override final method Baza::numeMet() in ...

- Deoarece metoda "numeMet()" este declarata cu atribut "final".4. Clase finale

Precum metodele declarate cu "final" nu mai pot fi modificate in sub-clasa copil, asa se pot crea si clase care sa ramana fixe, fara sa se poata crea din ele alta sub-clasa. Acest lucru se obtine prin adaugarea cuvantuluifinalinainte declass.- De exemplu:

Metode magice __get, __set, __call, __toString

In Programarea Orientata pe Obiecte (OOP) din PHP exista cateva metode mai speciale, care incep cu "__" (doua caractere '_'), precum__construct(). Acestea sunt numite genericMetode Magice(Magic Methods) si se executa automat in situatii mai speciale, cum ar fi de exemplu__get()pentru accesari de proprietati inexistente.In aceasta lectie sunt prezentate cateva din cele mai folosite astfel de metode:__get(), __set(), __call()si__toString().- Toate acestemetode magicetrebuie sa fie definite cu atributpublic.

1. Metode __get si __set

Metodele magice:__get()si__set()se folosesc de obicei impreuna si sunt create pentru lucru cu proprietati care nu sunt definite.

__get($name)- E apelata automat cand se acceseaza o proprietate care nu exista. Preia numele ei in parametru $name.

__set($name, $value)- Se apeleaza automat cand se atribuie o valoare unei proprietati care nu exista. Preia numele ei in parametru $name si valoarea in parametru $value.

Iata un exemplu din care se intelege mai bine rolul lor. O clasa in care sunt folosite aceste metode, se creaza o instanta de obiect la ea apoi e accesata o proprietate inexistenta.

- $prop e definita ca tip Array ca sa stocheze, prin metoda __set(), valorile atribuite unor proprietati nedefinite.- Cand prin instanta de obiect la clasa e accesata o proprietate care nu exista ($obj->noprop;), se executa automat metoda __get(). Aici e definita sa verifice in $prop daca are element cu cheia $name (numele proprietatii accesate), daca exista acel element, afiseaza valoarea lui, altfel, afiseaza un mesaj.- Cand se atribuie o valoare la proprietatea nedefinita ($obj->noprop = '...';), se executa automat metoda __set(). Aici e definita sa adauge in $prop un element cu numele proprietatii (cheie) si valoarea transmisa.Vedeti si explicatiile din cod.- Acest script va afisa urmatorul rezultat:Proprietateanopropnu exista.Proprietateanopropnu exista. S-a atribuit valoareaValoare pt. noprop - PHP OOPla proprietatea:prop['noprop']Valoare pt. noprop - PHP OOPVerificare: Valoare pt. noprop - PHP OOP

2. Metoda __call

Metoda magica __call()e creata pentru cazuri cand sunt apelate metode inexistente. Sintaxa ei este: __call($nume, $array_argumente)- $nume reprezinta numele metodei apelate- in $array_argumente sunt retinute intr-un Array argumentele adaugate la apelarea metodei.

In urmatorul exemplu e definita o astfel de metoda "__call()" care afiseaza un mesaj cu numele metodei inexistente care a fost apelata si argumentele transmise.

- In browser va afisa:Metodasitenu exista. Argumente:cursuri, tutorialeIncepand cu PHP 3.0 e adaugata o metoda similara,__callStatic(), aceasta se executa automat cand e apelata o metoda statica nedeclarata, prin formula: NumeClasa::metodaStatica()3. Metoda __toString

Cu metoda__toString()se determina modul de reactie a clasei cand instanta de obiect la ea este folosita ca o variabila de tip sir (String), de exemplu cu "echo".

In urmatorul exemplu e definita o clasa cu o metoda __construct() si una "__toString()" care afiseaza valoarea unei proprietati "mesaj".

- In browser va afisa:Fii bine primit

- Fara metoda __toString() adaugata in clasa, accesarea instantei de obiect simpla, cu "echo" sau "print" genereaza o eroare de genul:Catchable fatal error: Object of class AClas could not be converted to string in ...

Mai sunt si altemetode magice, mai putin folosite, cum ar fi:__isset(se apeleaza cand e verificata cu "isset()" o proprietate inexistenta),__invoke(se executa cand instanta de obiect e apelata ca o functie), si altele; le puteti gasi la pagina oficiala PHP.netMetode MagiceOOP - Clase abstract si interface

AbstractsiInterface(interfata) sunt tipuri declasemai speciale inOOP, pentru lucru mai avansat in programarea orientata pe obiecte.

1. Clase si Metode abstract

Clasele abstractese declara folosind cuvantulabstractinaintea lui "class".La aceste tipuri de clase nu se poate crea instanta de obiect, ele pot fi doar mostenite de alte clase extinse din ele.In clasele abstracte se definesc simetode abstracte, acestea se declara cu acelasi cuvant "abstract" si fara corpul de acolade, doar numele si parantezele rotunde, cu parametri necesari.- Iata un exemplu de clasa cu o proprietate "protected" o metoda abstracta si una accesor:

- Daca se creaza o instanta de obiect la aceasta clasa (de ex.:$obj = new Fructe();), va genera eroare de genul:Fatal error: Cannot instantiate abstract class

- Metodele abstracte se creaza doar in clase abstracte.- Rolul claselor si metodelor abstracte este acela de a crea un model minim de metode obligatorii care trebuie definite in sub-clase normale derivate din ele (cuextends). Metodele abstracte definite in cea parinte trebuie create in orice clasa copil extinsa din cea abstracta, cu acelasi numar de parametri (numele poate fi difereit).De ex., orice sub-clasa extinsa din clasa Fructe (definita mai sus) trebuie sa contina metoda Stoc() cu un parametru, cum ar fi cea din urmatorul exemplu, denumita Mere.

- Deoarece clasa Mere extinde Fructe, trebuie sa contina, pe langa alte elemente, si metodele abstracte declarate in aceea (anume Stoc(), cu un parametru). Daca aceasta sub-clasa nu ar avea metoda Stoc(), va genera eroare de genul:Fatal error: Class Fructe contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Mere::Stoc) in...

- Sub-clasele care extind o clasa abstracta pot fi utilizate normal, se pot crea si folosi instante de obiect la ele, mostenesc si pot folosi elementele cu atribut "public" si "protected" din cea parinte.De exemplu:

2. Interfaces

Ca rol, se poate spune caInterfaceeste asemanatoare cu clasa "abstract".ClasaInterfaceeste folosita ca tipar, sau template pentru clase cu functii similare, care trebuie sa respecte o anumita structura de metode.Sintetizat, Interface este o clasa cu o lista de metode obligatorii ce trebuie sa fie create in clasele unde este implementata. Toate metodele specificate in "Interface" sunt cu atributpublicsi trebuie sa fie definite in clasele in care e aplicata, avand acelasi numar de parametri cati sunt indicati in "Interface".

Creare interface

Clasa interfacese creaza similar cu celelalte tipuri de clase. Diferenta e aceea ca la definirea ei, in loc de cuvantul "class" se foloseste cuvantul "interface"; in plus, in corpul ei se scrie doar o lista cu metode publice fara, alt cod.Sintaxa generala este urmatoarea:

interface numeInterfata { public function numeMetoda(); public function altaMetoda() ...........}- La declararea metodelor in Interface nu se adauga acoladele sau codul lor, si nici alt atribut diferit de "public".

Iata un exemplu cu o Interface, denumita "ITest", in care sunt definite 2 metode: "Links()" si "Tutoriale()".

Implementare interface

Dupa ce a fost definit tiparul "interface", se pot crea clase care implementeaza metodele stabilite in acel tipar, respectand si numarul de parametri.Implementarea se face adaugand cuvantulimplementssi numele Interfatei la definirea claselor, dupa numele lor. class NumeClasa implements numeInterfata { // Instructiuni }Acestea trebuie sa contina in corpul lor toate metodele definite in "interface", cu atribut "public", si numarul de parametri stabiliti pt. fiecare (numele la parametri poate fi diferit). Pe langa acestea pot contine si alte metode.

Iata un exemplu cu o clasa care implementeaza interfata ITest creata mai sus.

- Metodele obligatorii (aici "Links()" si "Tutoriale()") respecta exact numarul de parametri stabiliti in "interface" "ITest". Alte metode (aici "setLink()") si proprietati sunt optionale, in functie de rolul fiecarei clase.- Numele parametrilor nu conteaza (observati ca in loc de $str s-a folosit $gen), dar numarul lor trebuie sa fie aceleasi ca in "interface".- Daca vreuna din conditii nu ar fi respectata in clasa, cum ar fi: nedefinirea unei metode, adaugarea de parametru in plus sau minus; scriptul genereaza eroare.Astfel, implementarea de "interface" este utila mai ales cand sunt create mai multe clase cu roluri similare si dorim ca acestea sa aibe toate o anumita ordonare si structura minima de metode, mai usor de retinut.3. Interface ca tip de date

Interfata poate fi utilizata si ca tip de data la parametri de functii, astfel, acel parametru poate fi utilizat ca instanta de obiect la orice clasa din cele ce folosesc acea "interface".Se intelege mai bine din urmatorul exemplu, in care e creata si folosita inca o clasa (LimbiStraine) ce aplica Tiparul din "ITest"; contine o proprietate si metodele obligatorii stabilite.

Intr-un script PHP se scrie urmatorul cod:

- Functia "cursuri()" creata cu aceasta formula intre acolade "function cursuri(ITest $obj)" face ca ea sa accepte ca argument doar obiect care are implementat "ITest".- Observati ca apeland functia cu argumente diferite, reprezentand numele instantelor la clase, foloseste parametru $obj ca instanta la clasa respectiva, si poate apela aceleasi metodele ("Links()" si "Tutoriale()") pt. fiecare deoarece aceste fiind specificate in "interface" ele trebuie sa existe in fiecare clasa ce apartine acelei Interfate, cu acelasi numar de parametri.- Prin aceasta tehnica nu mai e nevoie de a crea aceeasi functie pt. fiecare instanta.Acest exemplu va afisa in browser urmatorul rezultat:www.marplo.netphp-mysql-4Cale buna4-www.marplo.net/php-mysql