Minden, amit az objektumorientált PHP programozásról tudni érdemes

Minden, amit az objektumorientált PHP programozásról tudni érdemes

Milyen egyszerű, és szemléletes példákon keresztül mutathanánk be az úgynevezett objektumorientált PHP programozást? Miért érdemes feltétlenül tisztában lennünk mindezzel, ha szerveroldalra tévedünk?

Talán már te magad is hallottál az úgynevezett objektumorientált programozásról. Alapvetően sokféle objektumorientált nyelv létezik manapság: ilyenek például a Java, JavaScript, C++, C#, Php, és még sorolhatnánk.

Ebben a cikkemben az objektumorientált Php programozásról szeretnék kicsit bővebben beszélni. Miért érdemes megtanulnunk, mik az alapjai, és hogyan használható.

Miért érdemes megtanulnunk?

Habár a Php nyelven belül az objektumorientáltság támogatása nem olyan régre vezethető vissza (jó 10 évre)-tehát nincs feltétlenül akkora „múltja”, mint más programnyelvek esetén-ennek ellenére nagyon elterjedt manapság, a Php programozáson belül is.

Ennek oka egyértelműen arra vezethető vissza, hogy a mai világunk is, alapvetően objektumorientált. Nézzünk szét magunk körül: minden besorolható valamilyen egyértelműen definiált osztályba, és ezeknek vannak meghatározott tulajdonságaik. A járműveknek 2, vagy 4 kerekük van, a lepkéknek 2 szárnyuk, sőt, vannak olyan lepkék-az 1 fajhoz tartozók-melyek szinte pontosan ugyanúgy néznek ki.

Most képzeljük el, hogy hasonló osztályokat kell modelleznünk egy programozási feladat közben. Egyből eszünkbe jut, hogy nem lehetne-e valami jó szisztémát kitalálni arra, hogy ezt megtehessük úgy, hogy

  • Minél kevesebb legyen a hibalehetőség.
  • Átlátható legyen a munkánk.
  • Egyes tulajdonságok automatikusan következzenek egy adott elemre nézve, ha az egy osztályba tartozik.
  • Ne kelljen minden egyes elemhez újból változókat definiálni mindig és mindig.
  • Ha változtatni szeretnénk a hasonló elemek "jellemzőit", akkor azt elég legyen egy helyen megtenni.

Nos, pont erre jó az objektumorientált programozás (OOP), általánosságban véve. Hogy ezt megtehessük, mert a világunk is ilyen.

Mik az alapvető elemei az OOP-nak? Mik a lehetőségek?

Lépésről lépésre szeretném leírni, hogy mit hogyan lehet megtenni. Ahhoz, hogy valaki megértse ezeket, minimális szintű Php alaptudás szükséges, például tudni kell, hogy mi az változó, és a függvény.

Osztályok definiálása

class Jarmu{
	// definiált propertyk, függvények helye
} 

És ezzel létre is hoztuk az első osztályunkat. class, osztálynév, és utána {} jelek. Érdemes egy egységes szisztémát kialakítani, tehát minden osztálynevet nagybetűvel kezdeni, míg a változók, függvényeket neveit kicsivel.

Példányosítás, tulajdonságok és függvények definiálása

Minden egyes osztályon belül lehet tulajdonságokat (property), függvényeket (function) definiálni. A tulajdonságokat  definiálhatjuk akár konstansnak is, sima változóként, valamint később fogunk beszélni a „public, private, protected”, szintén függvényeknek, tulajdonságoknak, konstansoknak adható láthatóságról is, hogy ennek mi a jelentősége.

class Jarmu{
    var $nev = "Jármű";
    var $lehetseges_szinek=["zöld","kék","piros"];
    const LEHETSEGES_KEREKSZAM = [2,3,4];
    protected $fo_anyag = "fém";
    private $osszesen = 1200;
    public $mire_jo_ez = "utazni lehet vele";

    public function lehetsegesLampakSzama(){
        return [2,3,4];
    }
}

A példányosítás (instantiation) egy fogalom, ami bonyolultabbnak tűnik, mint ami valójában: egy osztályból, aminek vannak tulajdonságai, metódusai létrehozunk egy példányt. Mint amikor egy új autó kigurul a gyártósorról. Ez a new kulcsszóval tehető meg, a konstruktor neve mögé tehetünk ()-et ha szeretnénk. A zárójel abban az esetben lehet jó számunkra, ha a konstruktornak szeretnénk paramétereket adni. Ez után az példány elérhető változóira, függvényeire hivatkozhatunk a példányosításkor, amennyiben azok láthatóak (erről később).

$uj_jarmu = new Jarmu();
// a nev az osztalyban létező $nev tulajdonságra hivatkozik. Így kell egy objeuktum tulajdonságára hivatkozni. A kiírt szöveg: „Jármű”
echo $uj_jarmu->nev;

// akár meg is változtathatunk bizonyos tulajdonságot, ha szeretnénk 
$uj_jarmu->mire_jo_ez = "süvíteni lehet vele";
// a kiírt szöveg: „süvíteni lehet vele”;
echo $uj_jarmu->mire_jo_ez;

// új tulajdonságot is adhatunk a példánynak, amit eddig nem tettünk meg az osztályban
$uj_jarmu->uj_ertek = "ez egy új érték";
// kiírt szöveg: „ez egy új érték”
echo $uj_jarmu->uj_ertek;

Származtatás-nagyon egyszerűen

Felmerülhet bennünk a kérdés, hogy ha már van Jármű osztályunk, akkor lehetne egy az autók számára is. Bizonyos tulajdonságai automatikusan érvényesek lennének a jármű osztály tulajdonságai közül az autó osztályra, viszont szeretnénk újabb, specifikusabb dolgokat definiálni az új osztályban, ami csak arra jellemző. Esetleg, lehetséges, hogy általánosságban véve definiálunk valamit egy járműre (4 kereke van), mert az esetek nagy részében igaz, de felül szeretnénk írni bizonyos esetekben ezt a konvenciót. Egy származtatott osztály definiálása ugyanúgy történik, ahogy a sima osztályé, az „extends” kulcsszóval kiegészítve a definiálást.

class Auto extends Jarmu{
	// definiált tulajdonságok, függvények helye
} 

Öröklődés

Hogyan érhetjük el, hogy a Jármű osztály bizonyos tulajdonságai automatikusan érvényesek legyen az autóra is? Mi a technikai menete ennek? Ezt az úgynevezett láthatósággal (visibility modifiers) érhetjük el. Alapvetően 3 féle láthatóság létezik, ezek adhatók konstansoknak, tulajdonságoknak, és függvényeknek:

  • public: az egész Php kódunkban bárhol hivatkozhatunk rá.
  • private: csak és kizárólag abban az osztályban létezik, ahol definiáltuk. Nem származtatható más osztályokba, tehát alosztályokból sem lehet elérni, és sehol máshol sem a kódunkban.
  • protected: az ősosztályból származtatható az alosztályokba, és azokból elérhető, de a kód más részeiből nem.

Felmerülhet a kérdés, hogy miért van szükség erre a három láthatósági osztályra? Ennek egyetlen oka van: azt szeretnénk szabályozni, hogy ne férhessen mindenki hozzá az objektumok tulajdonságaihoz. Például, mikor az adatbázisból lekérdezünk valamit, és a kapott sorokat példányosított objektumokká alakítjuk, akkor nem szeretnénk, ha a személyes adatokhoz könnyebb lenne hozzáférni.

Hogyan szemléltethetjük a 3 féle láthatóságot? A példáinkhoz visszatérve: ha minden jármű fémből van, akkor minden autóra is igaz ez. Ezt így tehetjük meg:

class Jarmu{
    // ez lehetne akár protected is, viszont akkor nem lehetne KÖZVETLENÜL elérni. Csak egy másik függvény értékébe beletéve, ami vagy itt, vagy az alosztályban definiált.
	public $fo_anyag = "fém";
} 

class Auto extends Jarmu{
	// definiált tulajdonságok, függvények helye
} 

$auto = new Auto();
echo $auto->fo_anyag;

Ha azt szeretnénk, hogy a járműveknek legyen olyan tulajdonsága, ami nem öröklődik az alosztályokba, akkor egy private tulajdonságot definiálhatunk. Például, összesen 1200 jármű van, viszont ezt nem akarjuk származtatni sehova, mert az autókra ez már nem igaz: abból csak 600 van, és repülőgépből is, és ez teszi ki az 1200-at együtt. Ezt így tehetjük meg:

class Jarmu{
    private $osszesen = 1200;
} 

class Auto extends Jarmu{
	//protected $osszesen = 1200;
    public function getMind(){
        return $this->osszesen;
    }
} 

$auto = new Auto();

// nem fog kiírni semmit  errort dob az applikáció. Az autó osztályból nem érhető el a tulajdonság még függvények keresztül sem.
echo $auto->getMind();

 //nem fog kiírni semmit  errort dob az applikáció. Az autó osztályból nem érhető el a tulajdonság  közvetlenül.
echo $auto->osszesen;

Most nézzük az előző példát, de a $osszesen változó kegyen protected. Mi a különbség?

class Jarmu{
    protected $osszesen = 1200;
} 

class Auto extends Jarmu{
    public function getMind(){
        return $this->osszesen;
    }
} 

$auto = new Auto();

// ez 1200-at fog vissza adni. Működni fog, ugyanis az alosztály függvényeiben létezik, közvetett az elérés.
echo $auto->getMind();

 //nem fog kiírni semmit  errort dob az applikáció. Az autó osztályból nem érhető el a tulajdonság  közvetlenül.
echo $auto->osszesen;

Természetesen érdemes megjegyezni, hogy nem csak tulajdonságok, hanem konstansok, függvényekre is igaz ez az öröklődés, a lenti példa foAnyag() publikus függvénye látszódni fog nem csak az alosztályokban, máshonnan is. És mi van abban az esetben, hogyha azt szeretnénk elérni, hogy minden osztály a SAJÁT nevét írja ki ebben a mondatban? Tehát: „fém a fő anyaga az autó nevű konstrukciónak”, vagy „fém a fő anyaga a kamion nevű konstrukciónak”;

Megoldható, hogy az ősosztályban definiált függvénnyel egy, az alosztályban levő tulajdonságot érjünk el? Pontosan! Ez a lényege az OOP-nak: a származtatott függvények, és tulajdonságok pont olyanok, mintha az alosztályban definiáltuk volna őket. Csupán abban segít minket ez az elv, hogy a függvényeket elég legyen egy helyen létrehozni. Tehát:

class Jarmu{
	public $sajat_nev = "autó";
	protected $fo_anyag = "fém";

	public function foAnyag(){
		echo $this->fo_anyag. " a fő anyaga a". $this-> sajat_nev ." nevű konstukciónak";
   }
} 

class Auto extends Jarmu{
	public $sajat_nev = "autó";
} 

$auto = new Auto();
// kiírja,  hogy „fém a fő anyaga az autó nevű konstrukciónak”
echo $auto-> foAnyag();

Statikus, self

Minden egyes osztályban definiálhatunk statikus függvényeket, tulajdonságokat. Ha megfigyeltük, akkor eddig mindig csak példányosítás útján férhettünk hozzá a tulajdonságokhoz. Erre nem lenne mindig szükség, például, a jármű osztály korábban definiált neve $nev-ként van definiálva. Helyette használjuk a static kulcsszót:

class Jarmu{
 	static $nev = "Jármű";
}

Ekkor a következőképp hivatkozhatunk a Jarmu osztály nevére:

echo Jarmu::$nev;

$jarmu = new Jarmu();
//errort fog dobni. A régi módszer nem működik, a példányosítással
echo $jarmu->nev;

A self arra jó, hogy az osztályon belül a származtatott, és az adott osztályban definiált statikus tulajdonságokra, függvényekre hivatkozhatunk.

class Jarmu{
 	public static $darabszam = 1200;
	public static function miADarab(){
		return self::$darabszam;
    }
}

// kiírja, hogy 1200
echo Jarmu::miADarab();

Konstruktor

A konstruktor alapvetően arra való, ha valamit alapból meg szeretnénk tenni egy osztály példányosításakor.

class Jarmu{
	public function __construct(){
	    echo "ez alapból lehívódik mindig";
    }
}

// egymás után kiírja ezen a helyen kétszer, hogy „ez alapból lehívódik mindig”
$jarmu = new Jarmu();
$jarmu = new Jarmu();


A konstruktornak természetesen változókat is adhatunk.

class Jarmu{
    public $masik_param;
  
	public function __construct($parameter=null){
	    if(isset($parameter)){
			echo $parameter;
			
			$this->masik_param=$parameter;
			
			echo $this->masik_param;
		} else {
			echo "nem adtál meg semmit";
		}
    }
}

// kiírja hogy "PARAMÉTERPARAMÉTER"
$jarmu = new Jarmu('PARAMÉTER');
// kiírja, hogy "nem adtál meg semmit"
$jarmu = new Jarmu();

Na és mi a helyzet akkor, ha ezt csináljuk? Így van a konstruktor definiálva?

class Jarmu{
	public function __construct(){
	    die('meghaltam!');
    }
}

// egymás után NEM írja ki kétszer, az elsőnél megáll a kód.
$jarmu = new Jarmu();
$jarmu = new Jarmu();

Setterek, Getterek

Felmerülhet bennünk a kérdés, hogy ha létezik olyan láthatóság, ami csak az anyaosztályban van jelen, és azt sehol máshol nem tudjuk használni, akkor mi értelme van ilyeneket definiálni? Hisz sehol nem férhetünk hozzájuk.

A getterek, és setterek arra valók, hogy egy bármilyen, az objektumban jelen levő tulajdonságot megkaphassunk, illetve módosíthassunk (konstans természetesen nem módosítható). Mivel az osztályon belül definiált 2 függvény publikus, azokat bárhol meghívhatjuk.

class Jarmu{
	private $osszesen = 1200;
	public function getOsszes(){
		return $this->osszesen;
    }

    public function setOsszes(){
            return $this->osszesen = 2000;
    }
} 

$jarmu = new Jarmu();
// 1200-at ír ki
echo $jarmu->getOsszes();

// 2000-et ír ki
echo $jarmu->setOsszes();

Összefoglalás

Összeségében véve érdekes egy témakör. Az alapokat mindenképp érdemes tudni, én annak idején ennél többet nem tudtam, mikor interjúkra mentem, és sikeresen el tudtam helyezkedni Php programozóként. Manapság nagyon fontos az OOP szemlélet, ma már nem igen lehet munkát találni enélkül. A jó hír az, hogy ez egy olyan dolog, ami sokkal könnyebbé teszi az életünket, nem kifejezetten egy plusz teherként érdemes rá gondolni.

módosítva: 2020-05-16

Szeretnél árajánlatot kérni?

Nagy tapasztalattal rendelkezem weboldal készítés, webáruház készítés, keresőoptimalizálás és online marketing terén. Sok olyan munkám volt már, ami sikeres lett, és pénzt hozott az ügyfeleimnek.

Ajánlatkérés