PHPPamokos.lt


4. "Stebuklingi" metodai - konstruktoriai ir kt.

Prisiminkime tą pavyzdį, kad, kuriant klasės objektą, galima naudoti skliaustus. Kaip jau sakiau praeitoje pamokoje, tai reiškia, kad tuose skliaustuose galima perduoti parametrus. Kaip funkcijai. Logiška, ar ne? Tai šioje pamokoje pažiūrėsime, kas iš tikrųjų vyksta "už kadro" ir kaip tą panaudoti.

Sakykime, turime klasę class Person ir jos viduje turime asmens atributų - vardą, pavardę ir kt. Argi nebūtų smagu, jau kuriant klasės objektą, iš karto kaip parametrą paduoti tą vardą ir pavardę, ir toliau nebesigilinti, kaip klasė viduje su jais tvarkosi?

Paimkime dar kitą pavyzdį - mokesčius. Sakykime, kad turime klasę class Taxes, kuri skaičiuoja mokesčius, bet mes nežinome kokie mokesčiai yra toje konkrečioje šalyje ir konkrečiais metais. Pvz, gali keistis PVM ar minimali alga. Ar, kaip dabar Lietuvoje, euras vietoje lito. Tai būtent čia irgi praverčia iškart parduodami parametrai.

Ką čia filosofuoti - paimkime pavyzdį: sakykime, per metus uždirbome 50 000 Lt ir mums reikia paskaičiuoti gyventojų pajamų mokestį.

class Taxes { var $tax_rate; // mokesčio procentas function calculateTax($revenue) { return money_format('%.2n', $revenue * $this->tax_rate); } } $taxes = new Taxes; echo $taxes->calculateTax(50000);

Šiame pavyzdyje kuriame objektą, ir tada jo metodui paduodame vieną parametrą - mūsų uždirbtą algą. Tačiau kodas neveiks, nes $this->tax_rate nėra apibrėžtas. O būtų smagu paduoti mokesčio procentą kaip parametrą - tik ne vienai konkrečiai funkcijai, o visai klasei, kad tą parametrą galėtų naudoti visos tos klasės funkcijos.

$taxes = new Taxes(15); echo $taxes->calculateTax(50000);

Taigi, priėjome prie pirminio klasės sukūrimo metodo - konstruktoriaus. Yra rezervuotas metodo pavadinimas __construct() (būtent su dviem pabraukimo ženklais priekyje), kuris PHP klasėse bus kviečiamas automatiškai, kuriant klasę.

class Taxes { var $tax_rate; // mokesčio procentas function __construct($tax_rate) { $this->tax_rate = $tax_rate; } function calculateTax($revenue) { return money_format('%.2n', $revenue * $this->tax_rate); } function calculateProfit($revenue) { return money_format('%.2n', $revenue - $revenue * $this->tax_rate); } } $taxes = new Taxes(15); echo $taxes->calculateTax(50000); echo $taxes->calculateProfit(50000);

Štai tokiu būdu pasiekiame tikslą - kurdami klasę, paduodame jai parametrą mokesčių dydį, ir toliau nebesigiliname. Šiame pavyzdyje turime dvi skirtingas funkcijas, bet kaip parametrą turime paduoti mokesčių dydį tik vieną kartą - kurdami klasę. O po to jau klasė savo viduje naudoja $this.

Kiek prisimenu kai pats mokiausi objektinio programavimo, man sudėtingiausia buvo suprasti tokį kodą:

function __construct($tax_rate) { $this->tax_rate = $tax_rate; }

Tris kartus tax_rate??? Kaip čia suprasti?

Iš tikro, viskas čia yra labai logiška - čia yra du visiškai skirtingi kintamieji. Metodo skliausteliuose esantis $tax_rate yra metodo parametras, kuris naudojamas tik to metodo viduje ir daugiau niekur. Tai po lygybės ženklo esantis $tax_rate yra būtent tas pats. O $this-gt;tax_rate tai yra pačios klasės savybė-kintamasis, kuris klasėje apibrėžiamas kaip var $tax_rate. Ir jis jau prieinamas visos klasės viduje - bet kokiame jos metode. Ir nors šių dviejų kintamųjų pavadinimai vienodi - realiai jie skirtingi ir turi skirtingą prasmę.

Kiti "stebuklingi" metodai

PHP objektiniame programavime yra ir kitų "stebuklingų" metodų - jie taip ir vadinami "magic methods" ir jie visi prasideda nuo dviejų pabraukimo ženklų __. Jie yra naudojami labai retai, tai papasakosiu tik apie du - destruktorių ir objekto išvedimo metodą.

Destruktorius:

function __destruct() { // Write something to log }

Funkcija __destruct veikia priešingai konstruktoriui ir yra automatiškai kviečiama, kai klasė yra sunaikinama. O ji sunaikinama realiai dviem atvejais - arba kai visas skriptas baigia darbą (tada PHP automatiškai sunaikina visus resursus), arba kai yra daroma unset($object) konkrečiam klasės objektui.

Tiesą pasakius, destruktoriai nėra plačiai naudojami, ir pats asmeniškai sunkiai sugalvočiau atvejį, kada tai reikalinga - nebent kaip pavyzdyje kam nors įrašyti į logą, bet ir tai dažniausiai daroma kitose vietose. Bet galbūt pravartu žinoti, kad tokia OOP galimybė yra.

Kaip išvesti objektą į naršyklę:

function __toString() { echo $this->variable; }

Čia reikia paaiškinimų. Jeigu su klasės objektu jūs tiesiog iškviesite funkciją echo, tada gausite klaidą:

$class = new Klase; echo $class;
Catchable fatal error: Object of class Klase could not be converted to string

Tai norint išvesti objektą į naršyklę, yra du variantai - arba tai daryti su funkcijomis print_r arba var_dump, arba sukurti štai tokį metodą __toString klasės viduje, kuris ir nurodys, kas būtent turi būti išvedama su funkcija echo.

Daugiau "magiškų objektų" ir jų aprašymus galite rasti oficialioje PHP dokumentacijoje.



(c) 2015-2018. Visais klausimais kreipkitės povilas@laraveldaily.com