PHP - Klase i objekti


Što je objektno orijentirano programiranje?

Objektno orijentirano programiranje (OOP) je programski model koji se temelji na konceptu klasa i objekata. Za razliku od proceduralnog programiranja gdje je fokus na pisanju procedura ili funkcija koje izvode operacije nad podacima, u objektno orijentiranom programiranju fokus je na stvaranju objekata koji zajedno sadrže i podatke i funkcije. Objektno orijentirano programiranje ima nekoliko prednosti u odnosu na konvencionalni ili proceduralni stil programiranja. U nastavku su navedeni najvažniji:

  • Pruža jasnu modularnu strukturu programa.
  • Pomaže vam da se pridržavate principa "ne ponavljaj se", a time i vaš kod mnogo lakše održavati, mijenjati i uklanjati greške.
  • Omogućava stvaranje složenijeg ponašanja s manje koda i kraćim vremenom razvoja i visokim stepenom ponovne upotrebljivosti.

Sljedeći dijelovi će opisati kako klase i objekti rade u PHP-u.



Razumijevanje klasa i objekata

Klase i objekti su dva glavna aspekta objektno orijentisanog programiranja. Klasa je samostalna, nezavisna kolekcija varijabli i funkcija koje zajedno rade kako bi izvršile jedan ili više specifičnih zadataka, dok su objekti pojedinačne instance klase. Klasa djeluje kao prijedlog ili nacrt iz kojeg se može stvoriti puno pojedinačnih objekata. Kada se kreiraju pojedinačni objekti, oni nasljeđuju ista generička svojstva i ponašanja, iako svaki objekt može imati različite vrijednosti za određena svojstva. Na primjer, zamislite klasu kao nacrt kuće. Sam nacrt nije kuća, već je detaljan plan kuće. Objekt je poput stvarne kuće sagrađene prema tom nacrtu. Možemo izgraditi nekoliko identičnih kuća od istog plana, ali svaka kuća može imati različite boje, interijere i porodicu, kao što je prikazano na ilustraciji.




Klasa se može deklarisati pomoću ključne riječi class, nakon čega slijedi ime klase i para vitičastih zagrada ({}), kao što je prikazano u sljedećem primjeru. Stvorimo PHP datoteku koja se zove Rectangle.php i u nju stavimo sljedeći primjer koda kako bi naš kod klase trebao biti odvojen od ostatka programa. Tada ga možemo koristiti gdje god je potrebno jednostavnim uključivanjem datoteke Rectangle.php.

<?php
class Rectangle
{
    // Deklarisanje svojstva
    public $length = 0;
    public $width = 0;
    
    // Metoda za dobivanje opsega
    public function getPerimeter(){
        return (2 * ($this->length + $this->width));
    }
    
    // Metoda za dobivanje područja
    public function getArea(){
        return ($this->length * $this->width);
    }
}
?>

Ključna riječ public prije svojstava i metoda u gornjem primjeru je modifikator pristupa, koji ukazuje da je ovom svojstvu ili metodi moguće pristupiti s bilo kojeg mjesta. O tome ćemo saznati malo kasnije u ovoj lekciji.

Jednom kada je klasa definisana, iz nje se mogu kreirati objekti s novom ključnom riječi. Metodama i svojstvima klase može se direktno pristupiti putem ove instance objekta. Kreirajte drugu PHP datoteke i nazovite je test.php i u nju stavite sljedeći kod.

<?php
// Uključite definiciju klase
require "Rectangle.php";
 
// Stvorite novi objekt iz klase Rectangle
$obj = new Rectangle;
 
// Dobijte vrijednosti svojstava objekta
echo $obj->length; // ispisuje: 0
echo $obj->width; // ispisuje: 0
 
// Postavite vrijednosti svojstava objekta
$obj->length = 30;
$obj->width = 20;
 
// Ponovo pročitajte vrijednosti svojstava objekta kako biste prikazali promjenu
echo $obj->length; // ispisuje: 30
echo $obj->width; // ispisuje: 20
 
// Pozovite objektne metode
echo $obj->getPerimeter(); // ispisuje: 100
echo $obj->getArea(); // ispisuje: 600
?>

Simbol strelice (->) je OOP konstrukcija koja se koristi za pristup sadržanim svojstvima i metodama datog objekta. Dok pseudo-varijabla $this pruža referencu na pozivni objekt, tj. objekt kojem metoda pripada. Stvarna snaga objektno orijentisanog programiranja postaje evidentna kada se koristi više instanci iste klase, kao što je prikazano u sljedećem primjeru:

<?php
// Uključite definiciju klase
require "Rectangle.php";
 
// Stvorite više objekata iz klase Rectangle
$obj1 = new Rectangle;
$obj2 = new Rectangle;
 
// Pozovite metode oba objekta
echo $obj1->getArea(); // Ispisuje: 0
echo $obj2->getArea(); // Ispisuje: 0
 
// Postavljanje $obj1 vrijednosti svojstava
$obj1->length = 30;
$obj1->width = 20;
 
// Postavljanje $obj2 vrijednosti svojstava
$obj2->length = 35;
$obj2->width = 50;
 
// Ponovno pozovite metode oba objekta
echo $obj1->getArea(); // Ispisuje: 600
echo $obj2->getArea(); // Ispisuje: 1750
?>

Kao što možete vidjeti u gornjem primjeru, pozivanje metode getArea() na različitim objektima uzrokuje da ta metoda djeluje na različitom skupu podataka. Svaka instanca objekta je potpuno nezavisna, sa svojim svojstvima i metodama, pa se time može nezavisno manipulisati, čak iako su iste klase.



Korištenje konstruktora i destruktora

Da bi olakšao objektno orijentirano programiranje, PHP nudi neke čarobne metode koje se izvršavaju automatski kada se određene radnje dogode u objektu. Na primjer, čarobna metoda __construct() (poznata kao konstruktor) izvršava se automatski svaki put kada se kreira novi objekt. Slično tome, čarobna metoda __destruct() (poznata kao destruktor) izvršava se automatski kada se objekt uništi. Funkcija destruktora čisti sve resurse dodijeljene objektu nakon što se objekt uništi.

<?php
class MyClass
{
    // Konstruktor
    public function __construct(){
        echo 'Klasa "' . __CLASS__ . '" je pokrenuta!<br>';
    }
    
    // Destruktor
    public function __destruct(){
        echo 'Klasa "' . __CLASS__ . '" je uništena.<br>';
    }
}
 
// Kreiranje novog objekta
$obj = new MyClass;
 
// Izbacuje poruku na kraju datoteke
echo "Dostignut je kraj datoteke.";
?>

Destruktor se automatski poziva kada se skripte završe. Međutim, da biste eksplicitno aktivirali destruktor, možete uništiti objekt pomoću PHP funkcije unset(), kao u sljedećem primjeru:

<?php
class MyClass
{
    // Konstruktor
    public function __construct(){
        echo 'Klasa "' . __CLASS__ . '" je pokrenuta!<br>';
    }
    
    // Destruktor
    public function __destruct(){
    echo 'Klasa "' . __CLASS__ . '" je uništena.<br>';
    }
}
 
// Kreirajte novi objekat
$obj = new MyClass;
 
// Uništitava objekat
unset($obj);
 
// Izbacite poruku na kraju datoteke
echo "Dostignut je kraj datoteke.";
?>


Proširenje klase nasljeđivanjem

Klase mogu naslijediti svojstva i metode druge klase pomoću ključne riječi extends. Ovaj proces proširivanja naziva se nasljeđivanje. To je vjerovatno najsnažniji razlog korištenja objektno orijentiranog modela programiranja.

<?php
// Uključite definiciju klase
require "Rectangle.php";
 
// Definišite novu klasu na osnovu postojeće klase
class Square extends Rectangle
{   
    // Metoda za ispitivanje da li je i pravougaonik kvadrat
    public function isSquare(){
        if($this->length == $this->width){
            return true; // Kvadrat
        } else{
            return false; // Nije kvadrat
        }
    }
}
 
// Stvorite novi objekt iz klase Square
$obj = new Square;
 
// Postavite vrijednosti svojstava objekta
$obj->length = 20;
$obj->width = 20;
 
// Pozovite objektne metode
if($obj->isSquare()){
    echo "Površina kvadrata je ";
} else{
    echo "Površina pravougaonika je ";
};
echo $obj->getArea();
?>

Kao što možete vidjeti u gornjem primjeru, iako definicija klase Square ne sadrži eksplicitno metodu getArea() niti svojstvo $length i $width, instance klase Square mogu ih koristiti, jer su naslijeđene od roditeljske Rectangle klase.



Kontrola vidljivosti svojstava i metoda

Kada radite s klasama, možete čak ograničiti pristup njenim svojstvima i metodama koristeći ključne riječi vidljivosti za veću kontrolu. Tri su ključne riječi za vidljivost (od najvidljivijih do najmanje vidljivih): public, protected, private koja određuje kako i odakle svojstvima i metodama se može pristupiti i izmijeniti.

  • javno (public) - javnom svojstvu ili metodi može se pristupiti bilo gdje, unutar klase i izvan nje. Ovo je zadana vidljivost za sve članove klase u PHP-u.
  • zaštićen (protected) - zaštićenom svojstvu ili metodi može se pristupiti samo unutar same klase ili u podređenim ili naslijeđenim klasama, tj. klasama koje proširuju tu klasu.
  • privatna (privatno) - privatnom svojstvu ili metodi moguće je pristupiti samo unutar klase koja ga definiše. Čak ni podređene ili naslijeđene klase ne mogu pristupiti privatnim svojstvima ili metodama.

Sljedeći primjer će vam pokazati kako ova vidljivost zapravo funkcionira:

<?php
// Definicija klase
class Automobile
{
    // Deklarisanje svojstva
    public $fuel;
    protected $engine;
    private $transmission;
}
class Car extends Automobile
{
    // Konstruktor
    public function __construct(){
        echo 'Klasa "' . __CLASS__ . '" je pokrenut!<br>';
    }
}
 
// Stvorite objekt iz klase Automobile
$automobile = new Automobile;
 
// Pokušaj postavljanja svojstava $automobile objekta
$automobile->fuel = 'Benzin'; // ok
$automobile->engine = '1500 cc'; // fatal error
$automobile->transmission = 'Manual'; // fatal error
 
// Stvorite objekt iz klase automobila
$car = new Car;
 
// Pokušaj postavljanja svojstava objekta $ car
$car->fuel = 'Dizel'; // ok
$car->engine = '2200 cc'; // fatal error
$car->transmission = 'Automatic'; // undefined
?>


Statička svojstva i metode

Pored vidljivosti, svojstva i metode mogu se takođe deklarisati kao statičke, što ih čini dostupnim bez potrebe za instanciranjem klase. Statičkim svojstvima i metodama može se pristupiti pomoću operatora rezolucije opsega (::), poput ovog: ClassName::$property i ClassName::method(). Svojstvu deklarisanom kao statičko nije moguće pristupiti putem objekta te klase iako to može biti statička metoda, kao što je pokazano u sljedećem primjeru:

<?php
// Definicija klase
class HelloClass
{
    // Proglasite statičko svojstvo
    public static $greeting = "Hello World!";
    
    // Proglasite statičku metodu
    public static function sayHello(){
        echo self::$greeting;
    }
}
// Pokušaj direktnog pristupa statičkom svojstvu i metodi
echo HelloClass::$greeting; // Ispisuje: Hello World!
HelloClass::sayHello(); // Ispisuje: Hello World!
 
// Pokušaj pristupa statičnom svojstvu i metodi putem objekta
$hello = new HelloClass;
echo $hello->greeting; // Strogo upozorenje
$hello->sayHello(); // Ispisuje: Hello World!
?>

Ključna riječ self u gornjem primjeru znači "trenutna klasa". Nikada mu ne prethodi znak dolara ($) i uvijek iza njega slijedi operator :: (npr. Self::$name). Ključna riječ self razlikuje se od ove ključne riječi koja znači "trenutni objekt" ili "trenutna instanca klase". Ključnoj riječi this uvijek prethodi znak dolara ($), a iza nje slijedi operator -> (npr. $this->name).

Nadamo se da ste do sada razumjeli osnovne koncepte objektno orijentiranog programiranja. Više primjera za OOP pronaćićete u dijelu baze podataka PHP i MySQL.