Tredun ohjelmistokehittäjien kurssimateriaaleja
Yksi syy käyttää luokkia on se, että niiden kanssa voi käyttää periytyvyyttä, mikä vähentää koodin kirjoittamista ja tekee koodista joissakin tapauksissa monikäyttöisempää.
Periytyvyys tarkoittaa, että luokasta voidaan tehdä toinen luokka (tai monta uutta luokkaa), joka saa perimänsä luokan ominaisuudet, mutta sille voidaan lisätä vielä uusia ominaisuuksia. Luokkaa, josta tehdään uusi luokka, kutsutaan vanhemmaksi (parent) ja luokkaa, joka tehdään vanhemmasta, kutsutaan lapseksi (child).
Käytännön esimerkkinä voisi olla vaikkapa verkkokauppayrityksen järjestelmässä henkilö (lyhentämisen vuoksi luokasta puuttuu muun muassa getterit ja setterit).
<?php
class person {
protected $firstName;
protected $lastName;
protected $address;
protected $email;
protected $username;
protected $password;
}
public function __construct($first, $last, $addr, $emai, $user, $pass) {
$this->firstName = $first;
$this->lastName = $last;
$this->address = $addr;
$this->email = $emai;
$this->username = $user;
$this->password = $pass;
}
?>
Tästä pohjasta saattaisimme haluta luoda esimerkiksi asiakkaan, jolla on kaikki ylläolevat ominaisuudet, mutta myös joukko omia ominaisuuksia. Jotta voimme periyttää luokan, käytämme siihen sanaa extends.
<?php
class customer extends person {
protected $orderHistory[];
}
?>
Samasta person-luokasta voimme sitten tehdä toisen luokan, joka kuvaa työntekijää. Silloin sanotaan, että person on vanhempi-luokka ja customer ja employee ovat sibling eli sisarus-luokkia.
<?php
class employee extends person {
protected $department;
protected $salary;
protected $startDate;
}
?>
Tässä tehtävässä lähdetään miettimään kirjaston lainausjärjestelmää.
Jos emme lisää periytyneeseen luokkaan omaa constructoria, se voi käyttää suoraan vanhempi-luokan construktoria, jolloin oliota luodessa sille täytyy antaa vanhempi-luokan ominaisuudet.
lapsi-luokalle voidaan tehdä myös oma construktori, joka ottaa vastaan kaikki tarvittavat ominaisuudet, mutta ikään kuin lähettää vanhempi-luokassa olevat ominaisuudet sen construktorille. Huomioithan, että vain kaikki vanhempi-luokasta perittävät ominaisuudet lähetetään vanhempi-luokan construktorille, ei niitä, jotka ovat lapsi-luokan omia ominaisuuksia. Esimerkissä käytetään aiempaa customer-luokkaa.
<?php
class customer extends person {
protected $orderHistory[];
public function __construct($first, $last, $addr, $emai, $user, $pass, $history) {
parent::__construct($first, $last, $addr, $emai, $user, $pass);
$this->orderHistory = $history;
}
}
?>
Joskus vanhempi-luokassa on omia funktioita, joita voi kutsua myös lapsi-luokasta ja ne toimivat täysin. Kuitenkaan joskus emme haluakaan käyttää niitä samanlaisina, vaan muutamme niitä. PHP:ssä riittää, että kirjoittaa uuteen luokkaan saman funktion uudelleen halutuin muutoksin. Tätä kutsutaan overrideksi.
Ajatellaan, että person-luokassa olisi funktio, jolla vaihdetaan salasanaa.
<?php
class person {
protected $firstName;
protected $lastName;
protected $address;
protected $email;
protected $username;
protected $password;
}
public function changePassword($pass) {
$this->password = $pass;
}
?>
Tämä hyvin yksinkertainen funktio voi toimia asiakkaalla. Kuitenkin jos meillä on työntekijä, salasanalla on tietty määrä vaatimuksia turvallisuussyistä, jolloin täysin sama funktio ei kelpaakaan. Silloin voimme kirjoittaa funktion uudelleen.
<?php
class employee extends person {
protected $department;
protected $salary;
protected $startDate;
}
public function changePassword($pass) {
if (strlen($pass)> 8) {
$this->password = $pass;
}
else {
echo "Your password is too short";
}
}
?>
Joskus tahdomme, että luokka onkin sellainen, että siitä ei suoraan voi tehdä olioita, vaan siinä on ainoastaan ominaisuuksia ja funktioita, jotka on tarkoitus periä. Esimerkiksi emmehän me oikeasti ole kirjastoesimerkissä tekemässä yhtään oliota loanable-luokasta, koska mikä ihme se lainattava edes olisi? Sen sijaan me haluamme sen luokan, jotta teemme joukon uusia luokkia, joilla on tietyt ominaisuudet. Tällaista luokkaa, josta ei luoda olioita, kutsutaan abstraktiksi luokaksi.
Samaten luokan funktiot voivat olla abstrakteja eli silloin niissä ei lue, mitä ne funktiot tekevät, vaan ainoastaan tarkoittavat sitä, että abstraktin luokan lapsi-luokassa pitää olla samanniminen funktio, jossa sille oikeasti annetaan sisältö.
Luokasta tulee abstrakti, kun sen eteen kirjoitetaan abstract, samoin funktiosta. Funktion perään ei tule aaltosulkeita, vaan vain puolipiste.
<?php
abstract class person {
protected $firstName;
protected $lastName;
protected $address;
protected $email;
protected $username;
protected $password;
abstract public function changePassword($pass);
}
?>