PHP. Объектіге бағытталған бағдарламалау.

13 Наурыз 2015

PHP да процедуралық бағдарламалаумен қатар объектіге бағытталған бағдарламалау ОББ (ағылшынша - Object Oriented Programming яғни қысқаша OOP )да кең қолданылады.Қазіргі үлкен сайт жобаларын да осы ОББ қолданып жасайды.

Неге?

Мысалы, сіз бағдарлама кодын ОББ ның арқасында модульдерге бөліп жазуыңызға болады.

Ал деректер мен олар арқылы жасалатын іс-әрекеттер бір объектіде анықталатын болғандықтан, оларды керек кезде бірнеше рет шақырып кодыңызда пайдалануға болады.Тіпті оларды жаңа функциялармен толықтырып отыра аласыз.|

Және ең бастысы,объект дегенімізді нақты дененің сандық бейнесі деп есептесек,мысалы адамдар,машиналар не үйлер т.б. онда олардың не мақсатта қолданылатынын, бір-бірімен ол объектілердің қалай байланысатынын көз алдымызға елестете отырып бағдарлама жазуды  оңайлата аламыз.

Процедуралық  бағдарламалаудың негізгі құрылымы процедуралар мен функциялардан құралады және оларды пайдалану арқылы  бағдарламаның негізгі кодын бірнеше бөліктерге бөліп,керек кезде осы  код бөліктерін бірнеше рет шақырып қолдануға болады.Бірақ программист әрқашан процедура мен функциялардағы деректер енгізілетін параметрлерді есте сақтап отыруы керек.Өйтпеген күнде  оларға қосымша өзгеріс жасау қажет болғанда  қате жіберіп алуы мүмкін.Ал егер ондай қара күн туа қалса, онда ол  бағдарлама кодын қырыққабат аршығандай бірінен біріне өтіп тексеруге тура келеді.

Ал ОББ үшін өзгеріс жасау оп-оңай.Себебі объект барлық деректерін өз ішінде сақтайтын болғандықтан, айнымалыларды бір функциядан екінші функцияға өткізетін қажеттілік мүлдем туындамайды.

Осы ерекшеліктерді көзбен көру үшін, ОББ - объектіге бағытталған бағдарламалау дегенге мысалдар келтіре отырып, тереңірек үңіліп көруге тырысайық.Себебі, бұл тақырып өте маңызды, ол туралы мақалалар да өте көп жазылған.Сондықтан мен барымша жеткізіп, сол әлемді адаспай аралауға сіздерге бағыт беруге тырысамын.

Басында ОББ күрделі болып көрінгенмен,ұғына келе оңай игеріп кете аласыз.Түк қиындығы жоқ. 

Бұрын PHP деректеріне арналған сабағымда қысқаша осы ОББ туралы айтып өткенмін.Енді сол жазғанды әрі қарай толықтырып жалғастырмақпын.

Енді осы ОББ - объектіге бағытталған бағдарламалаудағы негізгі ұғымдарға рет ретімен тоқталып өтейік.

Негізгі ұғымдар-класс,объект,қасиеттері,әдістер.

Сонымен, класс деп, мысалға, салынуға арналған үй сызбасын айтуға болады.Сызбада үйдің барлық бөліктері,олардың неден жасалатыны жақсылап сипатталып суреттеледі.Сіз үйді ойша көзіңізге елестете аласыз.

Ал, объект дегеніміз осы сызба бойынша салынған кәдімгі үйлер.Қабырғалары нақты кірпіштен қаланған, белгілі мөлшерде есік-терезелері салынған нақты үй.

Бірақ, ол үйлер ешқандай өзара байланысы жоқ, ішкі безендірулерімен, ішінде тұратын адамдарымен және т.б. бір-бірлеріне ұқсамайтын болады - бір класстың объектілері де солай әртүрлі болып келеді.

Класс.

Класс дегеніміз объектінің негізін құрайды.Ол объектіні жасайтын айнымалылар мен осы айнымалыларды пайдаланатын функциялардан құралады.

Осы ОББ арқылы жасалатын сайт коды, әлбетте, бірнеше класстардан құралады.Олардың әрқайсысын жеке php -файл қылып сақтайды.Мысалға айтсақ,user.php, product.php, comment.php деген сықылды файлдар болып келеді.

Яғни, ОББ ның осындай ерекшелігі оның процедуралық бағдарламалаудан артықшылығын көрсетеді, себебі программист қай файлда не жатқанын керек кезде ілезде таба алады. 

Енді ескеретін бір нәрсе, бұдан былай осы айнымалылар мен функциялар деген сөздердің орнына оларды жаңа атауларымен,яғни класстың қасиеттері мен оның әдістері деп те атайтын боламыз.

Енді класстың синтаксисін жазып шығайын:

<?php
class MyClass
{
//Класстың қасиеттері мен әдістері
}
?>

Мұндағы жазылған class - классты белгілейтін арнайы сөз, одан кейінгі сөз MyClass - осы класстың атауы. Ал,бейнелі жақшалардың ішінде класстың қасиеттері мен әдістер орналасады.

Объект.

Енді осы класстың негізінде объект жасап шығару үшін келесі әдісті қолданамыз:

$obj = new MyClass;


Бұл жердегі $obj дегеніміз айнымалы.Осы айнымалы арқылы біз объектінің класста анықталған функцияларын ,яғни әдістерді шақыру арқылы нақты деректермен жұмыс істей аламыз.

Жоғарыда көрсетілген сілтемедегі өткен сабақты қайталап шықсаңыз құба-құп болар еді.Ол сабақта осы класс пен объект туралы жақсы баяндалып өткен.Сонымен қатар онда конструктор туралы да айтылып өтті.

Қасиеттер.

Қасиеттер дегеніміз жоғарыда айтып өткендей объектінің құрамына кіретін оның деректерінің мәндерін сақтайтын  айнымалылар. Олар екіге бөлінеді:

1. Объектінің қасиеттері,бұлар тек объектінің деректерін сақтайтын айнымалылар.

Мысалы:

$varObj;
немесе 
$varObj = "объектінің үнсіздік бойынша анықталған айнымалысының мәні";

2. Класстың қасиеттері,бұлар түгел класс бойынша анықталған деректерді сақтайтын айнымалылар.Яғни барлық класстың объектілеріне бірдей деректерді сақтайды - егер сондай жағдай орын алса ғана.

Мысалы:

static $varCls;
немесе 
static $varCls = "класстың үнсіздік бойынша анықталған айнымалысының мәні";


Бұл класстың қасиеттерін статикалық қасиеттер деп те атайды.Байқап отырғаныңыздай,айнымалының алдына арнайы "static" деген сөз жазылады. Бұлар туралы өткен сабақтарымның бірі Статикалық қасиет пен әдісте баяндап кеткенмін.Көрсетілген сілтеме бойынша естеріңізге түсірулеріңізге болады.

Әдістер.

Әдістер дегеніміз бұрын айтылып өткендей, кәдімгі функциялар.Демек, оларды "function" деген арнайы сөзбен анықтаймыз.Олар да қасиеттер сияқты екіге бөлінеді:

1. Объектінің функциялары немесе объект әдістері.Бұлар тек жоғарыда айтып өткен объектінің қасиеттерімен ғана жұмыс істейді және олармен арнайы сөз  "$this"- жалған айнымалы арқылы байланысып олардың мәндерін өзгерте алады.Бұл бұрынғы сілтемелер арқылы көрсеткен өткен сабақтарда баяндалып өткен .

Функцияның синтаксисі:

function FuncObj()
{
//Объект әдісінің коды, жалған айнымалы $this қолданылады
}


2. Статикалық әдістер немесе класстың функциялары.Бұл әдіс те жоғарыда сілтемеде көрсетілген өткен сабақта баяндалған.Статикалық әдістер тек статикалық қасиеттермен жұмыс істейді. Бұлар объектіні өзгерте алмайды, себебі бұл әдістерде жалған айнымалы $this пен жұмыс істеу мүмкіндігі жоқ.

Бұл  статикалық әдістің синтаксисі:

static function FuncCls()
{
//Статикалық әдіс коды, бұл кодта жалған айнымалы $this қолданылмайды.
}

Қасиеттер мен әдістердің көріну аумағы.(+ инкапсуляция туралы).

Объектімен, оның қасиеттері және әдістерімен қалай және қай жерден жұмыс істеуге мүмкіндік болатынын айқындау үшін көріну аумағы орнатылады. Көріну аумағынан тыс жерден оларға жүгіну қате болады. Бұл көріну аумағы қасиеттер мен әдістерге арнайы  үш кілттік сөзбен бекітіледі: "public", "private" және "protected". 

1. public.

Аты (қазақша - жалпы, жалпыға бірдей) айтып тұрғандай, осылай айқындалған қасиеттер мен әдістерге бағдарлама кодының кез келген жерінен жүгінуге, оларды шақыруға болады.

Егер қасиеттер мен әдістер ешқандай арнайы сөзбен белгіленбеген болса, онда олар үнсіздік бойынша "public" болып анықталады.

public $var;
public static $var;
public function Func() {  };
public static Func() {  };


2. private.

Бұл қазақша  жекеше  дегенді білдіреді, демек ерекше қорғалады деп те ұғынуға болады.Яғни, мұндай арнайы кілттік сөзбен анықталатын қасиеттер мен әдістерге тек класс ішінде сипатталған әдістердің ішінде ғана   жүгінуге болады.Бір сөзбен айтқанда олардың барын сырт көзден жасырып көрсетпейді.Бұл сыртқы қауіптерден сақтану үшін жасалған.

private $var;
private static $var;
private function Func() {  };
private static Func() {  };

3. protected.

Осындай кілттік сөзбен анықталатын қасиеттер мен әдістерді қазақша "қорғалған" деп атайды. Бұларға да "private" сияқты тек класста анықталған әдіс арқылы жүгінуге болады және қосымша кластың мұрагеріндегі әдістер арқылы да жүгіну мүмкіндігі берілген.

Сонымен, инкапсуляция (encapsulation - жасыру) дегеніміз объектінің сыртқа тек қажетті қасиеттері мен әдістерін қалдырып, ал қалған қасиеттер мен әдістерді  осы жоғарыда аталған "public", "private", "protected" кілттік сөздері арқылы өз ішінде жасырып сақтау қасиетін айтамыз.

Ия болмаса, инкапсуляция дегенді "қара жәшік" деген ұғыммен теңестіруге болады.Мысалы, алдымызда тұрған монитордың, не болмаса мышканың ішкі құрылысының қалай жұмыс іcтеп тұрғанын білмесек те біз оларды пайдаланамыз.Себебі, олардың ішкі құрылысы бізден жасырылып тұр - оларды тек жасаған адамдары біледі.

Инкапсуляцияның маңыздылығы сонда, объектінің ішінде қасиеттер мен әдістерді осылай сипаттап алып, кейін оны бағдарламаның кез келген жерінде шақырып қолдана беруімізге болады.

Мұрагерлік (+полиморфизм) деген не және ол не үшін керек?

Мұрагерлік (inheritance) дегеніміз ООБ принциптерінің бірі, ол бойынша басқа класстардың негізінде жаңа класстар жасау мүмкіндігі орын алады.Яғни осылай туындаған жаңа класс өзінің ата-аналық классының барлық қасиеттері мен әдістерін өзіне мұрагерлікке ала алады.Және осыларға қоса өзінің жеке қасиеттері мен әдістерін де осы өз классында анықтай алады.

PHP да тек бір класстан ғана мұрагерлер жасауға болады.Оны белгілеу үшін "extends" яғни қазақша "кеңейтілу" деген арнайы сөз қолданылады.

Енді осы жерде мен төменде келтірілген PHP кодында осы мұрагерлікті және жоғарыда баяндалып өткен қасиеттер мен әдістердің кейбірін мысал келтіріп жазып шықтым:

<?php
    //адамдар үшін класс ашайық
class People
{
    // жалпы статикалық қасиетке кез келген адам атын берейік
   public static $name = "Адам ";
    
    // Адам оқып іздене  алатынын статикалық әдісті сипаттайық
    public static function study()
    {
        echo self::$name . 'оқи біледі, іздене  алады <br />';
    }
}
 
    // жаңа класс Programmer бұл да адамдар тобы, демек ол People классына мұрагер класс бола алады
class Programmer extends People
{   
    // жекеше қасиет бағдарлама тілін сипаттайды делік
    private $lang ;
  
    // Адам бағдарламалар тілін үйреніп жүр
    public function Learn($lang)
    {
      echo self::$name . ' көп оқып еңбектенуінің арқасында '.$lang.' тілін үйреніп алды <br />';
      echo 'Енді '.self::$name .' сайт жазатын программист <br />';  
    }
}
echo People::$name.' <br>'; //Класстың статикалық қасиетіне (::) арқылы жүгініп,браузерге шығару
echo People::Study(); //Класстың статикалық әдісіне (::) арқылы жүгініп,оны браузерге шығарамыз

$coder = new Programmer(); //Мұрагер класстан объект осылай жасаймыз
$coder->Learn('PHP');//Объектінің әдісіне осылай (->) арқылы жүгінеміз

?>


Осы PHP кодын Notepad++ редакторына көшіріп, сосын оны php-файл ретінде сақтап алған соң Денвер арқылы браузерде шақырсақ былай болып шығады:


Мұрагерлік пен полиморфизм (көп пішінділік) бір-бірімен тығыз ұштасқан ұғым, басқаша айтқанда полиморфизм мұрагерлікті ұштап толықтырып тұрған механизм деп те айтуға болады.

Полиморфизм дегеніміз бір класстан жасалған әр түрлі объектілердің бір әрекетті әр түрлі тәсілмен орындауға мүмкіндік бере алатын  қасиеті.Осы полиморфизм арқылы  мұрагер класстарда мұрагерлікке берілген әдістерді қайта анықтап пайдалануға болады.

Сиқырлы әдістер (magic methods).

Екі төменнен сызылған сызықшалар арқылы басталып, кішкене әріптермен сипатталған әдістерді PHP да сиқырлы әдістер деп атайды.Бұл әдістердің маңыздылығы сонша, оларды PHP керек кезде өзі автоматты түрде шақырып алады.Ал сол керек кез туған жағдайда тосылып қалмас үшін, біз ол сиқырлы әдістерді алдын ала класстың ішіне сипаттап енгізіп қоюмыз  керек.

Енді сол сиқырлы әдістердің кейбіреулеріне тоқталып өтейін:

Конструктор.

Конструктор деп класстан new арқылы объект жасалған сәтте автоматты түрде бірге шақырылатын арнайы әдісті айтамыз.

Бұл әдіс не үшін қажет болуы мүмкін десеңіз, былай айтуға болады:

 Мысалы,объектіні алдын ала белгілі бір нақты мәндер арқылы жасау үшін, не болмаса "private","protected" сықылды қасиеттерді класстан тыс көріну аумағында өзгерту мүмкін еместігіне байланысты мұндай қасиеттерді тек осы конструктор немесе объектінің әдісінде мәндер беру арқылы өзгертуге болатындығы үшін деп айтуға болады.

Конструктор былай сипатталады: __construct 

Енді осы сиқырлы әдістің қалай жұмыс істейтінін көру үшін төмендегі жазылған PHP кодына көз салайық:

<?php
//User классын сипаттаймыз
class User{
//қасиеттерін сипаттаймыз
	public $name;
	private $email;
	private $pass;
	
	// конструктордың құрылымын көрсетеміз
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
	
	//қосымша getUserInfo() деген әдісті енгіземіз
	function getUserInfo(){
		echo "Аты-жөні: ".$this->name."<br>";
		echo "Поштасы: ".$this->email."<br>";
		echo "Пароль: ".$this->pass."<br>";
	}
}

$userobj = new User("Балхадиша", "balx@mail.ru", "123456");//осылай объект жасалады
	//getUserInfo() әдісі арқылы браузерге мәлімет жібереміз
	$userobj->getUserInfo();

?>


Сосын осы кодтың жұмысын браузерге шақырып қарайық:


Бұл жерде естеріңізде ұстайтын негізгі мәселе - объектідегі параметрлер арқылы жазылған мәндер конструкторға тікелей беріледі.

Деструктор.

Деструктор дегеніміз конструкторға қарама-қарсы ұғым.Бұл әдісті кодтың орындалуы аяқталып, объект өмір сүруін тоқтатқанда, яғни жойылғанда (мысалы, объектіге соңғы рет сілтеу жасалғанда) PHP интерпретаторы өзі шақырады және былай сипатталады __destruct. Аталған функцияда параметрлер болмайды. 

Бұл әдісті PHP да көп қолданбайды, бірақ кей кезде ол қажет болып қалуы мүмкін.Мысалы,объект жойыларда қандай да бір әрекеттер жасау үшін, мысалы ашық файлдарды жабу, не болмаса деректер базасымен байланысты үзу үшін пайдалануға болады.

Енді осы деструктордың жұмысын бақылайық, ол үшін оны жоғарыдағы кодтың ішіне енгізейік :

<?php
class User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
	
	// деструктор шақырылғанда браузерге хабарлама жіберейік
	function __destruct(){
		echo "Объект жойылды<br>";
	}
	
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
		echo "Аты-жөні: ".$this->name."<br>";
		echo "Поштасы: ".$this->email."<br>";
		echo "Пароль: ".$this->pass."<br><br>";
	}
}
     //енді объект жасаймыз
$userobj = new User("Балхадиша", "balx@mail.ru", "123456");
	//getUserInfo() әдісі арқылы браузерге мәлімет жібереміз
	$userobj->getUserInfo();
	
	//Осы кодтың соңын белгілейік
	echo "Бұл файлдың соңы<br>";
?>


Енді осы php коды жазылған файлды сақтап болған соң, браузерде Денвер арқылы қарайық:


Бірақ, біз кодтың біткенін күтпей-ақ, unset() функциясы арқылы деструкторды шақырып, объектіні қалаған кезде жоюымызға болады.

<?php
class User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
	
	// деструктор шақырылғанда браузерге хабарлама жіберейік
	function __destruct(){
		echo "Объект жойылды<br>";
	}
	
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
		echo "Аты-жөні: ".$this->name."<br>";
		echo "Поштасы: ".$this->email."<br>";
		echo "Пароль: ".$this->pass."<br><br>";
	}
}
     //енді объект жасаймыз
   $userobj = new User("Балхадиша", "balx@mail.ru", "123456");
	//getUserInfo() әдісі арқылы браузерге мәлімет жібереміз
	$userobj->getUserInfo();

     //объектіні  қалаған кезімізде жоя аламыз
	 unset($userobj);
	
	//Осы кодтың соңын белгілейік
	 echo "Бұл файлдың соңы<br>";
?>


Енді браузерден не шыққанын қаралық:


Көріп отырғаныңыздай, unset() функциясы арқылы біз объектіні қалауымызша скрипт бітпей-ақ жойып жібердік.

Объектіні тармақша түріне вйналдыру.

Кей кезде объектіні тармақша түрінде көрсету қажеттілігі туындайды.Ал бұлай жасау үшін бізге тағы бір сиқырлы әдістің көмегіне жүгінуімізге тура келеді.Өйтпеген күнде, скрипт жұмысы қатемен аяқталады.

Ол әдіс __toString() деп сипатталады.

Енді айтқандарымызға көз жеткізу үшін жоғарыда келтірілген php кодына сәл толықтырулар енгізейік.Алдымен, жаңа әдісті қолданбай, объектіні тармақша ретінде браузерге жіберіп көрелік:

<?php
class User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
   
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
    	return "Аты-жөні: ".$this->name."<br> 
	              Поштасы: ".$this->email."<br>
	              Пароль: ".$this->pass."<br><br>";
	}
}
     //енді объект жасаймыз
   $userobj = new User("Балхадиша", "balx@mail.ru", "123456");
   
	//echo арқылы объектімізді браузерге шығарып көрелік
	echo "Пайдаланушы туралы мәлімет: <br>".$userobj;

?>


Нәтижесінде браузерге скрипт қатемен аяқталғаны туралы хабарлама шықты:

 


Енді кодымызға __toString() сиқырлы әдісті енгізейік:

<?php
class User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
   
     //сиқырлы әдісті қолданайық
      public function __toString()
    {
        return $this->getUserInfo();
    }
   
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
    	return "Аты-жөні: ".$this->name."<br> 
	              Поштасы: ".$this->email."<br>
	              Пароль: ".$this->pass."<br><br>";
	}
}
     //енді объект жасаймыз
   $userobj = new User("Балхадиша", "balx@mail.ru", "123456");
   
	//echo арқылы объектімізді браузерге шығарып көрелік
	echo "Пайдаланушы туралы мәлімет: <br>".$userobj;

?>


Енді нәтижесі браузерде тармақша түрінде шықты:


Сеттер мен геттер.

Объектіге бағытталған бағдарламалау әлемінде сеттер мен геттер , немесе аксессорлар деген ұғым бар.

Олар да сиқырлы әдістерге жатады және былай сипатталады: __set() , __get()

Бұл әдістер егер кодта класстың анықталмаған, не болмаса рұқсат етілмеген қасиеттеріне жүгіну әрекеттері кездескенде PHP интепретаторы арқылы шақырылады.

Бұлар не үшін керек?! Өте керек, бір себебі жоғарыдағы баяндалып кеткен инкапсуляция принципі бойынша private қасиеттерге класстан тыс жерде жүгінуге болмайды.Ал егер қандай да бір қажеттілік туып калып, ондай қасиеттерге жаңа мәндер беру керек , не болмаса ол мәндерді оқу керек болса онда не істеуіміз керек.Міне осындай кезде бізге осы сеттер мен геттерлерді қолдануға тура келеді.

Сонымен, __get() әдісінде тек деректерді оқуға арналған бір ғана параметр болады - ол анықталмаған немесе жүгінуге болмайтын қасиеттің атауы  болады.

Ал, __set() әдісінің екі параметрі болады, анықталмаған немесе жүгінуге болмайтын қасиеттің атауы және оған берілетін мән.

Алғашында бұлар түсініксіз болуы мүмкін, бірақ бұл әдістердің жұмысын ұғынып алу өте маңызды.Сол үшін келесі мысалды қарастырайық:

<?php
class GetSet 
{
    // Деректерді сақтауға private массивті анықтайық. 
    private $data = array();
    // private қасиетке жүгіну салдарын көрсету үшін қосымша енгізілді
    private $myVar = "Мен тек класс ішінде қол жетімдімін.<br>";
    // $name класс ішінде анықталмаған қасиетке мән беру 
    public function __set($name, $value) 
    {
        echo $name."  қасиетіне ".$value." мәнін берейік.<br>";
        $this->data[$name] = $value;
    }
    // Анықталмаған қасиетке жүгіну 
    public function __get($name) 
    {
        echo  $name." қасиетін оқиық:<br>".$this->data[$name]."<br>";		
    }

    // private қасиетке тек осы әдісті пайдаланып жүгіне аламыз
    public function getInfo() 
    {
        return $this->myVar;
    }
}
     // Объект жасалық
     $obj = new GetSet;
     //Анықталмаған "apple" қасиетіне "қызыл" мәнін берейік.
     $obj->apple = "қызыл";
     //Анықталмаған "apple" қасиетінің мәнін браузерге шығарайық.
     echo $obj->apple . "<br>";

     echo "Private қасиетке бұл жерде әдіспен жүгіну дұрыс,демек  __get() бұл жерде шақырылмайды.<br>";
echo $obj->getInfo() . "\n"; echo "Private қасиетке бұлай дара жүгіну дұрыс емес,демек __get() бұл жерде шақырылады.<br>"; echo $obj->myVar . "\n"; ?>


Енді осы php файлды Денвер арқылы браузерге шақырсақ, нәтиже төмендегідей болады:


Соңғы қатарға зер салып қарасақ, біздің private қасиетке жүгінгеніміз қателікке әкеліп соққан жоқ,Бірақ, біз оның мәнін оқи алмадық - оның орнына қасиеттің атауын ғана көрсетті, бар болғаны сол.

Объектінің көшірмесін жасау.

Кейде объектінің көшірмесін жасау қажеттілігі туындайды.Ол үшін объектінің алдында арнайы сөз "clone" қолданылады.

Объектіні көшіргенде ол алдын ала конструктор сияқты автоматты түрде мәнге ие болуы керек қой. Міне, сондықтан осындай кезде тағы бір сиқырлы әдіске жүгінеміз.

Ол __clone() деп сипатталады және байқағаныңыздай оның параметрлері болмайды.Демек оған мәндерді тек ол әдістің ішінде ғана енгізе аламыз.Енді осыларды көзбен көру үшін тағы бір php кодын жазайық:

<?php
class User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
   
    // сиқырлы әдісті қолданып көшірмеге мәндер берелік
	function __clone()
	{
		$this->name = "Көшірме";
		$this->email = "copy@mail.ru";
		$this->pass = "";
	}
   
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
    	echo "Аты-жөні: ".$this->name."<br>"; 
	    echo "Поштасы: ".$this->email."<br>";
	    echo "Пароль: ".$this->pass."<br><br>";
	}
}
     //енді объект жасаймыз
   $userobj1 = new User("Балхадиша", "balx@mail.ru", "123456");
     // getUserInfo() әдісінен шыққан нәтижені браузерге шығаралық
   $userobj1->getUserInfo();
     //тағы бір объект жасалық
   $userobj2 = new User("Арман", "arma@mail.ru", "546668");
   $userobj2->getUserInfo();
     //енді $userobj1 объектісінің көшірмесін жасаймыз
   $userobj3 = clone $userobj1;
   $userobj3->getUserInfo();

?>


Енді кодтың жұмысынан шыққан нәтижені көрелік:


Ал егер объектінің көшірмесінің тіптен болмағанын қалайтын болсаңыз, онда жоғарыда сипатталған __clone() сиқырлы әдістің тек өзін, ішінде ешқандай  өрнектерсіз жазып қоюға тиісті боласыз.

Әдістерді қайта жүктеу.

Жоғарыда баяндалып өткен мұрагерлік тақырыбында мұрагер класс ата-аналық класстың кеңейтілген түрі , яғни ол ата-аналық класстың барлық қасиеттері мен әдістеріне қоса өзінің жеке қасиеттері мен әдістерін де анықтай алады делінген.

Демек, әдістерді қайта жүктеу деп, ата-аналық кластағы әдістерді мұрагер класста қайта анықтау.Осылай жасалған әрекеттің нәтижесінде, мұрагер класстағы әдіс ата-аналық класстағы әдісті ескере отырып қайта жүктеледі.Оны келесі php кодынан көруге болады.

Алдымен,бұл кодта не жазылатынын баяндап өтейін:

1. Жоғарыда өздеріңіз таныс болған User классына SuperUser мұрагер класс белгілейміз.

2. Сосын ол мұрагер класста оның өз конструкторы мен өз әдісін жазамыз.

3. Ата-аналық класстағы әдіске мұрагер класстан мынадай құрылғы parent:: "ата-аналық әдіс" арқылы жүгінеміз.

<?php
class User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
   
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
    	echo "Аты-жөні: ".$this->name."<br>"; 
	    echo "Поштасы: ".$this->email."<br>";
	    echo "Пароль: ".$this->pass."<br>";
	}
}

 // User классынан мұрагер класс жасаймыз
class SuperUser extends User{
	//оның өз жаңа қасиетін сипаттаймыз
	public $role;
	// оның өз конструкторын да анықтаймыз 
	function __construct($uname, $uemail, $upass, $urole){
	//оның ата-аналық классындағы конструкторға былай жүгінеміз
		parent::__construct($uname, $uemail, $upass);
	// және оның өз жеке қасиетін де ұмытпай анықтап кетеміз
		$this->role = $urole;
	}
	// енді getUserInfo() әдісін қайта жүктейміз
	function getUserInfo(){
		//оның ата-аналық классындағы getUserInfo()  әдісіне былай жүгінеміз 
		parent::getUserInfo();
		//оның қосымша анықталған өз қасиетін осылай браузерге шығарамыз
		echo "Ролі: ".$this->role."<br>";
	}
}  

   //енді мұрагер класстан объект жасаймыз
   $userobj = new SuperUser("Әкімгер", "admin@mail.ru", "adm2015", "1");
   
	//осы объектінің getUserInfo() әдісін шақыралық
	echo $userobj->getUserInfo();

?>


Енді осы php файлды Денвер арқылы браузерге шақырайық:


Класстарды қалай автоматты түрде жүктеуге болады?

Жоғарыда айтып өткенімдей, класстарды жеке-жеке файлдар ретінде, мысалы User.php,Article.php т.с.с.  деп жазып,сосын керек кезде кодтың ішінде require, include сықылды PHP нұсқауларын қолданып ол файлдарды шақырып алуымызға болады.

Енді түсінікті болу үшін екі php коды жазылған файлдарды сипаттап шығалық.Алдымен,мен өзім тест жасау үшін пайдаланатын testphp директорияда (каталог немесе папкада) тағы 2 директориялар ашпақпын, яғни  testclass және testobj деген.

Алдымен testclass директориясында  классты сипаттайтын "user.php" файлды жазып шығу керек:

<?php
class Testclass_User{
	public $name;
	private $email;
	private $pass;
	
	// конструктор
	function __construct($uname, $uemail, $upass){
		$this->name = $uname;
		$this->email = $uemail;
		$this->pass = $upass;
	}
   
	//қосымша getUserInfo() деген әдіс
	function getUserInfo(){
    	echo "Аты-жөні: ".$this->name."<br>"; 
	    echo "Поштасы: ".$this->email."<br>";
	    echo "Пароль: ".$this->pass."<br>";
	}
}


Сосын testobj директориясында негізгі орындалатын "userobj.php" файлына мынадай php кодын жазып шығайын:

<?php
// testphp/testclass/ директориясындағы файлға апаратын жолды белгілейміз
set_include_path('..'.PATH_SEPARATOR.'/testphp/');

   // жүктелуге қосылатын класстың атын функция параметрі түрінде сипаттау
   function autoloader($className){
    $path = str_replace('_', '/', strtolower($className));
     return include_once $path.'.php';
  }
   // файлды автоматты түрде жүктейтін функция 
   spl_autoload_register('autoloader');

   // класстан объект жасаймыз
   $userobj = new Testclass_User("Айна", "aina@mail.ru", "ai_Na2015");
   
	//осы объектінің getUserInfo() әдісін шақыралық
	echo $userobj->getUserInfo();
	
?>


Енді testobj директориясында орналаcқан "userobj.php" файлын Денвер арқылы шақырайық.Ойлағанымыздай, ол Testphp_User классын жүктеді және нәтижесі былай болып шықты:



Енді кодтың ішінде жазылған сіздерге таныс емес функцияларға жеке-жеке қысқаша тоқталып өтейін:

1. set_include_path('..'.PATH_SEPARATOR.'/testphp/');

Бұл функция require, include т.т. сықылды нұсқаулардың жолай қосылатын файлдарды  іздейтін  директориялар тізіміне жаңа мән беру арқылы өзгеріс жасайды.Басқаша айтқанда, php.ini деген конфигурациондық файлдың include_path директивасында айқындалған файлға апаратын жолға өзгеріс жасалынады.

Бұл жерде PATH_SEPARATOR - директорияларды ажыратып тұратын тұрақты таңба.Ол Windows те былай сипатталады (;), ал Unix те  былай (:).

2. spl_autoload_register('autoloader'); 

Бұл функция new арқылы объект жасағанымызда оның параметрінің ішінде берілген класстың аты бойынша файлды жоғарыдағы set_include_path() де берілген директорияда іздей бастайды.Егер табылса, оны сол директориядан жүктейді.

3. Сыртқы файлдарды қосып алу.

Файлдарды PHP да оның мынандай арнайы нұсқауларын пайдаланып қосып алуымызға болады.Олар мыналар:

include
require
include_once
require_once


include

Бұл нұсқау берілгенде PHP интерпреторы оның орнына параметрінде жазылған файлдың кодын көшіріп жаза салады.Енді бұл қалай жұмыс істейтінін көрсету үшін php коды арқылы екі  файлды жазып шығайын.

Біріншісінде екі айнымалыны мәндерімен белгілейміз және ол файлдың атын "vars.php" деп атайық:

<?php  
  $var1 = 100;
  $var2 = 200; 
?> 


Екінші файлды sum.php деп атап,оның ішіне жоғарыдағы "vars.php" файлын "include" арқылы қосалық:

<?php  
  // екі файл да бір директорияда жатқандықтан,оларға 
  // баратын жолды set_include_path арқылы белгілемейміз
  include 'vars.php';
  $sum = $var1+$var2;
 echo "Қосындысы: ". $sum."<br>"
?>


Сосын осы sum.php файлын Денвер арқылы браузерде шақырсақ, былай болып шығады:


include_once

Бұл нұсқаудың жұмыс істеу принципі жоғарыда айтылып өткен include нұсқауы сияқты.Тек айырмашылығы - бір рет қосылған файлдың коды екінші рет қайталанбайды.

Енді осы айтқанымызды дәлелдеу үшін, жоғарыдағы "sum.php" файлын жаңадан "sums.php" файлының кодына екі рет қосып жазып, не шығатынын көрелік: 

<?php  
  include 'sum.php';
  include 'sum.php';
?>


Енді осы файлды браузерді жүктесек былай болып шығады:


Көріп отырғаныңыздай, "sum.php" файлындағы код екі рет қайталанып отыр.Енді екінші нұсқауды былай "include_once" ке өзгертіп жазайық. 

<?php  
  include 'sum.php';
  include_once 'sum.php';
?>


Енді браузерде "sums.php" файлын қайта жүктейік:


Көздеріңіз жетіп отырғандай, "include_once" нұсқауы алдыңғы файлдағы кодты қайталап қосқан жоқ.

require және require_once

Бұл нұсқаулардың жоғарыда көрсетілген нұсқаулармен жұмыс істеу қағидаттары ұқсас.Тек бір айырмашылығы, егер қосылуға тиіс файл табылмаса, скрипт жұмысын тоқтатады.

Ал "include" және  "include_once" нұсқаулары ондай жағдай туа қалса, тек ескерту жібереді де әрі қарай скрипт орындала береді. 


4. $path = str_replace('_', '/', strtolower($className))

  Функция  str_replace(search, replace, subject)  тармақшаны өңдейтін функция болып табылады.Яғни, берілген "subject" тармақшасындағы ізделініп отырған "search" жаңа "replace" -пен алмастырылып қайтарылады.

Мына мысалды $path = str_replace('_', '/', strtolower($className)) қаратырсақ, $className алдымен "strtolower" функциясы арқылы кіші әріптерге айналады,сосын ол тармақшадағы "_" таңбасы "/" таңбасымен алмастырылады.

Яғни,біздің жағдайымызда класстың атауы "Testclass_User" ді  "testclass/user" ге  алмастыру арқылы, екі қоянды бір оқпен аттық - класстың атауына оның орналасқан директориясы мен ол сипатталған файлдың атауын бірдей сидырдық.Неге бұлай жасағанымызды кейінгі сабақтарда түсінетін боласыздар. 

Егер мақала көңіліңізден шықса, онда онымен төмендегі түйме арқылы достарыңызбен бөлісіңіз

Пікірлер