Clase, obiecte si metode in PHP

0

Ce sunt clasele si metodele ?

O clasa este o colectie de variabile si metode. Aceste componente locuiesc impreuna pentru a servi aceluiasi scop, pentru care au fost scrise.O clasa poate fi folosita ca un mod elegant de a organiza date si functionalitati, asemanator cu o colectie de functii si variabile.

Probabil ca cea mai simpla metoda de a intelege acest concept este crearea efectiva a unei clase.

Prima clasa

O clasa este creata folosind cuvantul cheie class. In varianta cea mai simpla, contine cuvantul cheie, un nume si doua acolade.

 


 

 

Numele clasei poate contine orice combinatie de litere si cifre, caracterul underscore _ , dar nu poate incepe cu o cifra.

Clasa creata mai sus este perfecta, desi nu poate fi folosita, inca, la nimic. Pentru a utiliza aceasta clasa, cream obiectele:

 


 

 

In forma, cel putin, instantierea unui obiect este asemanatoare cu apelarea unei functii. Ca si la functii, unele clase necesita sa le transmiti argumente. De asemenea, trebuie sa folosesti cuvantul cheie new. Astfel ii spui interpretorului PHP ca declari un obiect nou. Obiectul nou creat poate fi stocat intr-o variabila, pentru utilizari ulterioare.

Proprietati

In corpul unei clase, poti declara variabile speciale, numite proprietati. In PHP 4 acestea trebuiau declarate cu cuvantul cheie var in fata




Aceasta sintaxa este in continuare acceptata (in PHP 5), dar doar pentru a asigura compatibilitate cu versiuni anterioare de PHP.

In PHP 5, proprietatile pot fi declarate ca publice, private sau protejate

 


 

 

Dupa cum se poate vedea, poti sa declari o proprietate si sa ii asociezi o valoare in acelsi timp. Poti „trage cu ochiul” la starea unui obiect folosind functia print_r()

 


 

 

va afisa pe ecran

 


 

 

Poti accesa proprietatile obiectelor folosind operatorul „->”. Ca atare, „$ro->tip” inseamna proprietate $tip din obiectul Dictionar referentiat de „$ro”. Daca poti accesa o proprietate, inseamna ca poti sa ii obtii / setezi si valoarea. Codul urmator instantiaza doua obiecte Dictionar. Schimba proprietatea $tip la unul dintre obiecte si adauga traduceri la amandoua.

 


 

 

Scriptul de mai sus va returna

 


 

 

 

Acum clasa Dictionar a inceput sa devin utila. Obiecte individuale pot stoca seturi distincte de chei si valori, ca de altfel si identificatorul care ii spune userului mai multe despre ce tip de dictionar este.

Desi clasa Dictionar este in momentul de fata un pic mai mult decat o serie de array-uri asociative, exista un indiciu catre puterea obiectelor aici. In stadiul actual, putem reprezenta codul nostru, la fel de bine, si astfel:


 

 

Desi structura de mai sus indeplineste exact acelasi scop ca si clasa Dictionar, nu garanteaza insa structura. Daca ai trimis un obiect Dictionar, stii sigur ca acesta are proprietatea $traduceri. Intr-un array (tablou) asociativ, nu mai exista aceeasi garantie. Acest lucru face o cerere de forma $en[‘traduceri’][‘COPAC’]; sa rateze intr-un fel sau altul, exceptand cazul in care codul ce genereaza cererea este absolut sigur de provenienta array-ului respectiv.

Desi sunt beneficii in stocarea datelor in obiecte, ratam o intreaga dimensiune. Obiectele pot FI lucruri, intr-adevar, dar crucial este ca ele pot FACE lucruri.

Metode

Intr-o forma simpla, metodele sunt functii declarate in interiorul unei clase. Sunt de obicei – dar nu intotdeauna – apelat prin intermediul unei instante de obiect folosind operatorul „->”

 


 

rezultatul va fi


 

Dupa cum poti observa, metoda sumar() e declarata la fel ca orice functie, doar ca s-a realizat prin intermediul clasei. Metoda sumar() este apelata prin o instanta a obiectului Dictionar, folosind operatorul „->”. Functia sumar() acceseaza proprietati pentru a oferi o scurta trecere in revista a statusului unui obiect.

Ai observat, probabil, folosirea unei facilitati noi. Pseudo-variabila $this ofera un mecanism pentru obiecte prin care se pot referi la propriile proprietati si metode. In afara unui obiect, este un identificator pentru a-i accesa elementele ($ro in cazul nostru). In interiorul unui obiect, nu exista un astfel de identificator, deci trebuie sa utilizezi $this. Daca crezi ca $this produce confuzie, incearca sa-l inlcouiesti in minte cu „instanta curenta”, atunci cand il intalnesti in cod.

Clasele sunt adesea reprezentate in diagrame, folosind UML (Universal Modeling Language sau „Limbaj de Modelare Universal”). Detaliile despre UML nu fac obiectul acestui articol, dar fara discutii, reprezinta o metoda excelenta de a vizualiza relationarile dintr-o clasa.

Constructorul

Motorul PHP recunoaste un numar de metode „magice”. Daca sunt definite, ele apeleaza metode automat, atunci cand circumstantele sunt favorabile. Una dintre cele mai cunoscute de astfel de metode este metoda constructor. Motorul PHP apeleaza un constructor in momentul in care obiectul este instantiat. Este locul unde pui instructiuni esentiale pentru obiectul tau. In PHP 4, creezi un constructor declarand o metoda cu acelasi nume ca al clasei. In PHP 5, declari o metoda intitulata „__construct()”.
 


 

 

Pentru a initializa un obiect Dictionar trebuie sa transmiti, catre constructorul sau, un string si un obiect DictionarIO. Constructorul foloseste acesti parametri pentru a-si seta propriile proprietati. Iata cum poti instantia un obiect Dictionar:

 


 

 

Clasa Dictionar este mult mai sigura decat pana acum. Stii ca orice obiect Dictionar va fi initializat cu argumentele care trebuie.

Desigur, in momentul de fata, nu exista nici un mod prin care poti opri pe cineva sa nu revina ulterior si sa schimbe proprietatea $tip sau sa seteze $dictio in NULL. Din fericire, PHP 5 te poate ajuta si in acest caz.

 Cuvinte cheie :

Ai facut cunostinta deja cu cuvantul cheie „public” in relatia lui cu proprietatile. Un cuvant cheie declara vizibilitatea unei proprietati. Concret, o proprietate poate fi setata ca fiind public, privata sau protejata. Proprietatile publice pot fi scrise si citite din exteriorul clasei. Proprietatile private pot fi setate numai in contextul unui obiect sau clase. Proprietatile protejate pot fi accesate doar in interiorul clasei curente sau a claselor care o mostenesc. (vom discuta si despre Mostenire in cadrul acestui articol). Poti folosi proprietati private pentru a-ti bloca intr-adevar clasele. Daca declari proprietatile ca fiind private si incerci sa le accesezi din afara clasei, motorul PHP va returna o eroare.

 


 

 

va returna o eroare de forma:  Fatal error: Cannot access private property /  Dictionar::$dictio in…

In general, este indicat sa-ti faci toate proprietatile private, si apoi sa oferi metode pentru a le accesa, daca este necesar. In acest fel, poti controla interfata clasei, facand unele date read-only, curata sau filtra argumente inainte de a le transmite proprietatilor si oferi un set clar de reguli prin care se poate interactiona cu un obiect.

Poti modifica visibilitatea metodelor in acelasi cu fel in care o faci cu proprietatile, adaugand „public”, „private” sau „protected” in declaratia metodei. Daca clasa ta contine niste metode de uz intern, de care lumea de afara nu trebuie sa stie, le poti declara private. In urmatorul exemplu, o metoda „obtine()” ofera o interfata pentru utilizatorii clasei Dictionar pentru a extrage traduceri. De asemenea, clasa trebuie sa urmareasca si pastreze toate cererile, de aceea ofera o metoda privata, „memoreazaCerere()” pentru acest scop.


 


Declarand memoreazaCerere() ca fiind privata simplifica interfata publica si protejeaza clasa de apelari gresite sau nepermise a metodei memoreazaCerere(). Ca si la proprietati, orice incercare de a apela metoda privata din afara clasei va genera o eroare fatala.

Lucrand in contextul clasei

Metodele si proprietatile pe care le-ai intalnit pana acum lucreaza toate in contextul obiectului. Altfel spus, trebuie sa le accesezi folosind instante al obiectului, prin intermediul pseudo-variabilei $this sau a unei referinte stocate intr-o variabila normala / standard. In unele cazuri, vei constata ca este mult mai util sa accesezi proprietatile si metodele prin intermediul unei clase decat al unei instante de clasa. Membri de acest fel ai clase sunt cunoscuti sub numele de static (statici).

Pentru a declara o proprietate statica, pune cuvantul cheie „static” dupa modificatorul de vizibilitate, direct inaintea numelui proprietatii.

Exemplul de mai jos arata o singura metoda statica „$dic_dir”, care contine calea catre directorul implicit unde vor fi salvate si de unde vor fi citite datele pentru Dictionar. Pentru ca aceaste date sunt aceleasi pentru toate obiectele, este normal sa le facem disponibile tuturor instantelor de obiecte.

 


 

 

Poti accesa o proprietate statica folosind un operator ce consta din doua puncte duble „::”. Acesta se plaseaza intre numele clasei si numele proprietatii statice pe care o accesam

 


 

 

Dupa cum observi, nu este nevoie sa instantiezi un obiect Dictionar pentru a accesa aceasta proprietate.

Sintaxa folosita pentru a declara si accesa metode statice este similara.


 

 

Utilizatorii nu mai pot accesa directorul proprietatii $dic_dir. Creand metode speciale pentru accesarea proprietatii, te poti asigura ca orice valoare furnizata este de incredere. In acest caz, metoda verifica daca stringul furnizat indica un director in care se poate scrie, inainte de a realiza asocierea valorii.

De mentionat ca ambele metode fac referire la proprietatea $dic_dir folosind cuvantul cheie „self” si operatorul „::”. Nu poti folsi $this intr-o metoda statica pentru ca $this face referire la instanta curenta a obiectului in sine, iar metoda statica este apelata prin intermediul clasei si nu a obiectului. Motorul PHP observa $this in metoda statica si returneaza o eroare si un mesaj informativ.

Pentru a apela o metoda statica din exteriorul clasei, foloseste numele clasei, operatorul „::” si numele metodei

 


 

 

Exista doua motive destul de bune pentru care vrei sa folosesti metode statice. Inainte de toate, o operatiune anume poate ca nu necesita instantierea unui obiect pentru a-si atinge scopul. Declarand static, il scutesti pe utilizator de „efortul” de a crea un obiect nou. Apoi, o metoda statica este disponibila global. Asta inseamna ca ii poti seta o valoare pe care toate instantele o pot accesa, facand din metoda statica un mod excelent de a transmite seturi de date in sistem.

In timp ce proprietatile statice sunt declarate private pentru a preveni utilizari ne-permise, exista o cale de a crea o proprietate statica blocata pentru doar citire: o poti declara ca fiind constanta. Ca si verisorul sau global, o constanta este ne-modificabila, odata ce a fost definita. Este utila pentru statusuri sau alte aspecte care nu se schimba pe parcursul unui proces, cum este de exemplu constanta Pi (3.14…..), sau lista actuala a tarilor din Europa.

O constanta o declari folosind cuvantul cheie const. De exemplu, din moment de o implementare reala a clasei Dictionar va folosi mai mult ca sigur o baza de date in spate, poti sa presupui ca va exista un numar maxim de termeni si traduceri.

 


 


Constantele unei clase sunt intotdeauna publice, de aceea nu poti folosi un cuvant cheie pentru vizibilitate. Dar acest lucru nu reprezinta o problema pentru ca orice incercare de a schimba valoarea unei constante va rezulta intr-o eroare. De asemenea, noteaza ca spre deosebire de proprietatile normale, numele constantelor nu incep cu semnul „$”.

Mostenirea

Relatia dintre dintre clase obiectele dinamice pe care ele le genereaza permite o foarte mare flexibilitate in sistem. Obiecte Dictionar de sine statatoare incapsuleaza seturi distincte de date, dar totusi modelul pentru aceste diferite entitati este definit intr-o singura clasa Dictionar.

Cateodata, trebuie sa impui / scrii variatii la nivel de clasa. Iti mai amintesti de termenul „DictionarIO” ? Ca recapitulare, obtine date de la obiectul Dictionar, le scrie in log-uri, obtine date de la log-uri si le furnizeaza inapoi in obiectul Dictionar.
 


 

 

Aces exemplu introduce o serie de metode simple – in special caArray(), care returneaza o copie a array-ului $traduceri. Implementarea DictionarIO are virtutea simplitatii. Ca de obicei, pe parcursul codului exemplificat pana acum, verificarea erorilor a fost ignorata, dar chiar si asa, este o metoda rapida si usoara de a salva datele intr-un fisier.

Din momentul in care ai pus la dispozitie o librarie de acest gen, curand va trebui sa te dedici formatului in care vei salva datele. Un format depasit va risca bunatatea si rabdarea utilizatorilor care poate fac copii de rezerva (back-up) in acest fel. Specificatiile se vor schimba si vei primi plangeri despre faptul ca rezultatul nu va putea fi editat cu usurinta. Unii utilizatori poate vor dori sa exporte datele catre terte parti, folosinf formatul XML.

In momentul de fata ai o problema. Cum sa suporti ambele formate in spatele interfetei Dictionar ?

O solutie ar fi sa folosesti condtii in interiorul metodelor exporta() si importa(), folosind un status, asa cum este exemplificat in continuare:

 


 

 

Aceasta structura a codului nu arata prea bine, datorita faptului ca se bazeaza pe cod duplicat. Cand se realizeaza o schimbare intr-un loc (adaugand un nou format, de exemplu), modificarea trebuie realizata si in celelalte locuri unde se mai utilizeaza tipul de date, astfel codul poate deveni repede greu de intretinut / optimizat / modificat.

Mostenirea este o solutie mult mai eleganta. Poti crea o noua clasa XMLDictionarIO care mosteneste interfata realizata in DictionarIO, dar supra-scrie o parte din functionalitate.

O clasa copil o creezi folosind cuvantul cheie extends. Iata o implementare simpla:
 


 

 

Acum XMLDictionarIO este functional identica cu DictionarIO. Pentru ca mosteneste toate atributele publice (si protejate) ale clasei DictionarIO, poti aplica acelasi actiuni si unui obiect XMLDictionarIO pe care le aplici si obiectului DictionarIO. Relatia extinde tipul obiectului. un obiect XMLDictionarIO este, evident, o instanta a clasei XMLDictionarIO, dar este, de asemenea, si o instanta a clasei DictionarIO, in acelasi fel in care o persoana este un om, un mamifer si un animal, toate in acelasi timp, si in aceasta ordine a generalizarii. Poti testa acest lucru folosind operatorul „instanceof”, care returneaza TRUE daca obiectul este un membru al clasei indicate.

 


 



Rezultatul este

 


 



Asa cum „instanceof” accepta ca $dictio este un obiect DictionarIO, la fel o vor face si metodele care accepta aceste obiecte ca argumente. Asta inseamna ca obiectul XMLDictionarIO poate fi transmis constructorului clasei Dictionar, desi DictionarIO este tipul specificat de semnatura constructorului.

O implementare rapida a XMLDictionar, ce utilizeaza DOM (Document Object Model) pentru functionalitatea sa XML

 


 

Detaliile despre obtinerea si generarea de XML pot fi luate ca atare. Sunt foarte multe metode prin care se poate realiza, inclusiv prin excelenta extensie SimpleXML. Pe scurt, metoda importa() ia un document XML si il foloseste pentru a popula obiectul Dictionar. Metoda exporta() ia datele din obiectul Dictionar si le scrie intr-un fisier XML. Intr-o aplicare reala vei folosi probabil un format bazat pe XML, numit XLIFF, format potrivit pentru importul in instrumente ale unor terte parti.

Noteaza ca ambele metode, importa() si exporta() apeleaza utilitarul cale(), care nu exista in clasa XMLDictionarIO. Acest lucru nu are importanta pentru ca cale() este implementat in DictionarIO. Cand XMLDictionarIO implementeaza o metoda, aceasta implementare este apelata pentru un obiect XMLDictionarIO, cand metoda este apelata. Cand nicio implementare nu este prezenta, apelarea merge in clasa parinte.

 

 

Leave A Reply