در قسمت قبل به مبحث کلاس‌ها پرداختیم، در این قسمت قصد داریم ارث بری کلاس‌ها از هم و همچنین مبحث سطح دسترسی را با هم بررسی کنیم.

ارث بری کلاس ها

در شیء گرایی مجبوریم کلاس‌هایی بوجود بیاوریم که از همدیگر خصوصیاتی را به ارث می‌برند. در کلاس‌ها همیشه کلاس سطح بالا را کلاس والد و کلاس سطح پایین تر را کلاس فرزند کلاس والد می‌نامیم.

البته ممکن است کلاس فرزند هم به خودی خود، یک کلاس پدر برای کلاس دیگری به حساب آید.

در پایین یک کلاس به نام Father و یک کلاس به نام Child تعریف می‌کنیم که کلاس Child فرزند کلاس Father به حساب می‌آید:

<?php
class Father{
	public $lastName="Rezaei";
	public $firstName;
}
class Child extends Father{
	public $firstName;
}
$Ali = new Father();
$Ali->firstName = "Ali";
echo $Ali->firstName." ".$Ali->lastName;
echo "<br>";
$Mahdi = new Child();
$Mahdi->firstName= "Mahdi";
echo $Mahdi->firstName." ".$Mahdi->lastName;
?>

همانطور که می‌بینید برای ارث بری کلاس Child از کلمه کلیدی extends استفاده نمودیم.

از آن جایی که lastName برای پدر و فرزند یکی است آن را تنها در کلاس Father تعریف کردیم.

بعد از تعریف کلاس‌ها یک شی به نام Ali از کلاس Father ایجاد کردیم و برای آن firstName را مقدار دهی کردیم. در سطر 11 به سادگی نام و نام خانوادگی شیء Ali را چاپ کردیم.

در سطر 12 با چاپ <br> به سطر بعدی می‌رویم.

در سطر 13 یک شی از روی Child ایجاد و در سطر بعد به firstName آن مقدار دادیم.

در آخرین سطر نیز به سادگی نام و نام خانوادگی شیء Ali را چاپ کردیم.

همانطور که می‌بینید کلاس Child اصلا Property با نام lastName ندارد ولی باز بدلیل ارث بری از کلاس Father این مقدار را برای ما چاپ کرد.

Method و Property از نوع static

static کردن یک متد یا پراپرتی باعث می‌شود که دیگر نیاز به ایجاد یک نمونه از کلاس نباشید و بدون ایجاد نمونه به متد یا پراپرتی دسترسی داشته باشیم.

برای static کردن یک متد یا پراپرتی قبل از نام آن‌ها از این کلمه کلیدی استفاده می‌کنیم. مثال:

<?php
class Car{
	static public function getSpeed(){
		return "240";
	}
}
echo Car::getSpeed();
?>

همانطور که در سطر یکی مانده به آخر می‌بینید بدون نیاز به ایجاد یک شیء از کلاس Car و تنها با دو علامت دو نقطه این فراخوانی را انجام داده و عدد 240 در خروجی چاپ می‌شود.

در متدهای static برای فراخوانی پراپرتی ها، باید آن‌ها از نوع static بوده و از کلمه کلیدی this استفاده نمی‌کنیم. در عوض از کلمه کلیدی self به همراه دو، دو نقطه استفاده می‌کنیم. مثال:

<?php
class Car{
	static public $speed= "240";
	static public function getSpeed(){
		return self::$speed;
	}
}
echo Car::getSpeed();
?>

همانطور که می‌بینید برای دسترسی به پراپرتی speed از self استفاده کردیم.

سطوح دسترسی در برنامه نویسی شیء گرا

در قسمت قبل، پیش از تعریف Method یا Property از کلمه کلیدی public استفاده نمودیم. این کلمه کلیدی سطح دسترسی یک Property یا Method را معین می‌کند.

سطوح دسترسی PHP به شرح زیر هستند:

public: این سطح دسترسی باعث می‌شود که Method و یا Property در همه جا اعم از کلاس‌های دیگر و در اشیاء نیز قابل دسترس باشند.

protected: این سطح دسترسی باعث می‌شود که Method و یا Property‌ها تنها در کلاس‌های فرزند قابل فراخوانی باشند.

private: این سطح دسترسی باعث می‌شود که Method تنها در کلاس اصلی قابل دسترسی باشد.

مثال زیر را با هم ببینیم:

class Father{
	public $father_public= "father_public";
	protected $father_protected= "father_protected";
	private $father_private= "father_private";
}

اگر یک شیء از کلاس فوق ایجاد کنیم تنها قادر به فرخوانی fahter_public هستیم، و ما بقی قابل فراخوانی نیستند:

$Father = new Father();
echo $father_public;

اگر کلاس Child را از کلاس Father فوق extends کنیم تنها قادر به استفاده از متد public و protected هستیم. مثال:

<?php
class Father{
	public $father_public= "father_public";
	protected $father_protected= "father_protected";
	private $father_private= "father_private";
}
class Child extends Father{
	public function getFather_public(){
		return $this->father_public;
	}
	public function getFather_protected(){
		return $this->father_protected;
	}
}
$Child = new Child();
echo $Child->getFather_public();
echo "<br>";
echo $Child->getFather_protected();
?>

همانطور که در بالا می‌بینید در کلاس Child دو متد از نوع public ایجاد کردیم تا درون آن‌ها به Property‌های کلاس Father دسترسی پیدا کرده و آن‌ها را در اشیاء صدا بزنیم و بررسی کنیم که آیا قابل فراخوانی هستند یا خیر.

در مثال بالا و در کلاس Child تنها می‌توانیم به Property‌های public و protected دسترسی داشته باشیم و امکان دسترسی به پراپرتی‌های private کلاس پدر وجود ندارد.

اگر یک کلاس به نام Mother ایجاد کنیم تنها می‌توانید به پراپرتی‌های public کلاس Father دسترسی داشته باشید به شرطی که بعد از کلمه کلیدی public از کلمه کلیدی static استفاده کنیم:

class Father{
	public static $father_public= "father_public";
}
class Mother{
	public function getFather_public(){
		return Father::$father_public;
	}
}
$Mother = new Mother();
echo $Mother->getFather_public();
?>

همانطور که در بالا می‌بینید کلا Mother از کلاس دیگری extends نشده ولی باز می‌تواند به پراپرتی public کلاس‌های دیگر دسترسی داشته باشد.

Getter‌ها و Setter ها

معمولا اگر یک Property از نوع private و یا protected باشد برای مقدار دهی و یا مقدار گیری از آن در خارج کلاس از مفهوم توابع Getter و Setter با سطح دسترسی public استفاده می‌شود. مثال زیر را ببینید:

<?php
class Father{
	private $username;
	public function setUsername($value){
		$this->username = $value;
	}
	public function getUsername(){
		return $this->username;
	}
}
$Father = new Father();
$Father->setUsername("user1");
echo $Father->getUsername();
?>

همانطور که در بالا می‌بینید پراپرتی username از نوع private است بنابراین خارج کلاس نه می‌توانیم آن را فراخوانی کنیم و نه آن را تغییر دهیم، بنابراین دو متد setUsername و getUsername را به ترتیب برای مقدار دهی و مقدار گیری از متد username بوجود آوردیم.

Overide کردن

مثال زیر را ببینید:

<?php
class Father{
	public $name= "Ali";
	public function getName(){
		return "My Name is: ".$this->name;
	}
}
class Child extends Father{
	public $name= "Mahdi";
	public function getName(){
		return "My Name is: ".$this->name;
	}
}
$Child = new Child();
echo $Child->getName();
?>

در مثال فوق متد getName کلاس Father را در کلاس Child در واقع Overide کردیم. پس برای Overide کردن یک متد، یک متد با همان نام ایجاد می‌کنیم.

در Overide کردن برای دسترسی به متدهای والد می‌توان از کلمه کلیدی parent بهره برد:

<?php
class Father{
	public $name= "Ali";
	public function getName(){
		return "My Name is: ".$this->name;
	}
}
class Child extends Father{
	public $name= "Mahdi";
	public function getName(){
		echo "Called From Child => ";
		return parent::getName();
	}
}
$Child = new Child();
echo $Child->getName();
?>

 همانطور که می‌بینید در متد getName کلاس Child متد getName کلاس Father را Overide کرده و آن را تغییر دادیم. ابتدا متن echo چاپ شده و در نهایت return متد getName کلاس Father را فراخوانی می‌کند. در نهایت خروجی مانند زیر خواهد بود:

Called From Child => My Name is: Mahdi

البته متغیر name مقدارش را از متغیر کلاس Child دریافت می‌نماید.