تا این مرحله از دورهٔ آموزش OOP در PHP بارها و بارها با کیورد public
برخورد داشتهایم که این کلیدواژه در کنار کلیدواژگان protected
و private
تحت عنوان Access Modifier شناخته میشوند. به عبارتی، این کلیدواژگان مشخصکنندهٔ سطح دسترسی پراپرتیها و متدهای داخل این کلاس هستند. برای آن که به طور عملی با این سطوح دسترسی آشنا شویم، داخل پوشهٔ oop
پروژهای تحت عنوان access-modifier
ساخته و ساختار پروژههای قبلی را داخل آن ایجاد میکنیم. در ادامه، داخل پوشهٔ classes
فایلی تحت عنوان Visibility.php
ساخته و آن را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class Visibility
{
public $publicProperty = "Public Property";
protected $protectedProperty = "Protected Property";
private $privateProperty = "Private Property";
public function showPublicMethod()
{
echo "This is a public method\n";
}
protected function showProtectedMethod()
{
echo "This is a protected method\n";
}
private function showPrivateMethod()
{
echo "This is a private method\n";
}
}
کلاسی همنام با نام این فایل تحت عنوان Visibility
ساخته و داخل بدنهٔ آن سه پراپرتی تعریف کرده و به ترتیب سطوح دسترسی protected
،public
و private
را برای آنها در نظر گرفتهایم. در ادامه، سه متد مختلف نیز با سطوح دسترسی protected
،public
و private
ساختهایم که تنها کاری که قرار است انجام دهند آن است که استرینگی را چاپ کنند. در ادامهٔ این آموزش، ابتدا به معرفی عملکرد این سطوح پرداخته سپس در عمل خواهیم دید که چگونه کار خواهند کرد.
آشنایی با سطح دسترسی public
همانطور که از نام این Access Modifier مشخص است، کیورد public
یک سطح دسترسی سراسری در اختیار پراپرتیها یا متدهای داخل یک کلاس قرار میدهد به طوری که هیچ گونه محدودیتی در دستیابی به آنها از جایجای سورسکد وجود نخواهد داشت.
آشنایی با سطح دسترسی protected
سطح دسترسی protected
به معنای «محافظتشده» بوده و حاکی از آن است که پراپرتیها و متدهایی که از جنس protected
باشند، فقط و فقط از طریق همان کلاسی که داخلش تعریفشدهاند و همچنین کلاسهای فرزندی که از آن کلاس ارثبری کردهاند در دسترس خواهند بود.
آشنایی با سطح دسترسی private
محدودترین سطح دسترسی در این بین private
است به طوری که پراپرتیها و متدهایی از این جنس فقط و فقط از طریق همان کلاسی که داخلش تعریف شدهاند قابلاستفاده خواهند بود.
حال که با مفهوم تکتک سطوح دسترسی آشنا شدیم، جهت تست کلاس Visibility
که پیش از اقدام به ساختش کردیم، وارد فایل index.php
شده و کدهای زیر را داخل آن مینویسیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
echo $obj->publicProperty;
echo "\n";
echo $obj->protectedProperty;
echo "/n";
echo $obj->privateProperty;
ابتدا از روی کلاس Visibility
آبجکتی تحت عنوان obj$
ساخته سپس هر سه پراپرتی را به این آبجکت منتسب کرده تا با استفاده از دستور echo
مقادیر آنها را چاپ کنیم. چنانچه این فایل را از طریق کامندلاین و یا مرورگر اجرا کنیم، در خروجی خواهیم داشت:
/var/www/oop/access-modifier$ php index.php
Public Property
PHP Fatal error: Uncaught Error: Cannot access protected property SokanAcademy\Visibility::$protectedProperty in /var/www/oop/access-modifier/index.php:8
Stack trace:
#0 {main}
thrown in /var/www/oop/5-access-modifier/index.php on line 8
همانطور که در خروجی ملاحظه میشود، مقدار پراپرتی publicProperty$
که از جنس public
میباشد به درستی چاپ شده است اما دو پراپرتی دیگر که از جنس protected
و private
هستند منجر به بروز ارور شدهاند و این ارور حاکی از آن است که امکان دسترسی به پراپرتی protectedProperty$
را نخواهیم داشت. با توجه به این که این پراپرتی منجر به بروز ارور شده است، مفسر پیاچپی دیگر به بررسی پراپرتی آخر که privateProperty$
نام دارد نخواهد رسید که جهت تست این موضوع، میتوانیم کدهای فوق را به صورت زیر تغییر دهیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
echo $obj->publicProperty;
echo "\n";
// echo $obj->protectedProperty;
// echo "/n";
echo $obj->privateProperty;
در حقیقت، خطی که مسئول چاپ پراپرتی protectedProperty$
بود را کامنت کرده و مجدد فایل فوق را اجرا میکنیم:
/var/www/oop/access-modifier$ php index.php
Public Property
PHP Fatal error: Uncaught Error: Cannot access private property SokanAcademy\Visibility::$privateProperty in /var/www/oop/access-modifier/index.php:10
Stack trace:
#0 {main}
thrown in /var/www/oop/5-access-modifier/index.php on line 10
همانطور که انتظار میرفت، امکان دسترسی به پراپرتیهایی هم که از جنس private
هستند را نخواهیم داشت. این موضوع در ارتباط با متدهایی هم که سطوح دسترسی متفاوتی دارند صادق است به طوری که داریم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
// echo $obj->publicProperty;
// echo "\n";
// echo $obj->protectedProperty;
// echo "/n";
// echo $obj->privateProperty;
$obj->showPublicMethod();
$obj->showProtectedMethod();
$obj->showPrivateMethod();
پس از کامنت کردن کدهای مرتبط با چاپ پراپرتیها، هر سه متد تعریفشده داخل کلاس Visibility
را فراخوانی کردهایم به طوری که در خروجی خواهیم داشت:
/var/www/oop/access-modifier$ php index.php
This is a public method
PHP Fatal error: Uncaught Error: Call to protected method SokanAcademy\Visibility::showProtectedMethod() from context '' in /var/www/oop/access-modifier/index.php:12
Stack trace:
#0 {main}
thrown in /var/www/oop/5-access-modifier/index.php on line 12
میبینیم که مجدد امکان دسترسی به متدهایی هم که از جنس protected
یا private
هستند را نخواهیم داشت.
پیش از این گفتیم که پراپرتیها و متدهایی که از جنس protected
باشند فقط از داخل همان کلاس و کلاسهای دیگری که از آن ارثبری کنند در دسترس هستند که برای روشنتر شدن این موضوع، کلاس Visibility
را به صورت زیر تغییر میدهیم:
<?php
namespace SokanAcademy;
class Visibility
{
public $publicProperty = "Public Property";
protected $protectedProperty = "Protected Property";
private $privateProperty = "Private Property";
public function __construct()
{
echo "The protected property is: $this->protectedProperty\n";
echo "The private property is: $this->privateProperty\n";
$this->showProtectedMethod();
$this->showPrivateMethod();
}
public function showPublicMethod()
{
echo "This is a public method\n";
}
protected function showProtectedMethod()
{
echo "This is a protected method\n";
}
private function showPrivateMethod()
{
echo "This is a private method\n";
}
}
حال فایل index.php
را به صورت زیر آپدیت میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
// echo $obj->publicProperty;
// echo "\n";
// echo $obj->protectedProperty;
// echo "/n";
// echo $obj->privateProperty;
// $obj->showPublicMethod();
// $obj->showProtectedMethod();
// $obj->showPrivateMethod();
در واقع، با توجه به این که کانستراکتور به محض ساخت یک آبجکت از روی کلاس فراخوانی میشود، صرفاً با ساخت یک آبجکت از روی کلاس Visibility
میتوانیم عملکرد آن را تست کنیم به طوری که در خروجی خواهیم داشت:
/var/www/oop/access-modifier$ php index.php
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
میبینیم که به سادگی از داخل همان کلاس توانستیم به پراپرتیها و متدهایی که از جنس protected
یا private
بودن دست یابیم. پیش از این گفتیم که سطح دسترسی protected
این امکان را در اختیارمان میگذارد تا علاوه بر دسترسی داشتن از داخل همان کلاس، در کلاسهای فرزندی که از کلاس والد ارثبری میکنند نیز در دسترس خواهند بود که به منظور تست این موضوع، داخل پوشهٔ classes
فایلی تحت عنوان ChildClass.php
ساخته و آن را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class ChildClass extends Visibility
{
}
تنها کاری که کردهایم آن است که با استفاده از کیورد extends
گفتهایم که کلاس ChildClass
کلیهٔ ویژگیهایش را از کلاس Visibility
به ارث خواهد برد. در ادامه، قصد داریم تا داخل فایل index.php
آبجکتی از روی کلاس ChildClass
بسازیم به طوری که خواهیم داشت:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
// echo $obj->publicProperty;
// echo "\n";
// echo $obj->protectedProperty;
// echo "/n";
// echo $obj->privateProperty;
// $obj->showPublicMethod();
// $obj->showProtectedMethod();
// $obj->showPrivateMethod();
$child = new SokanAcademy\ChildClass();
echo $child->publicProperty;
echo "\n";
$child->showPublicMethod();
آبجکت جدیدی تحت عنوان child$
از روی کلاس ChildClass
ساخته و اگر چه که داخل کلاس ChildClass
هیچ کدی ننوشتهایم، اما در عین حال با توجه به این که کلاس مذکور کلیهٔ خصوصیاتش را از کلاس والدِ Visibility
به ارث برده است، به پراپرتی و متد public
قرار گرفته داخل کلاس پدر دسترسی خواهیم داشت به طوری که در خروجی داریم:
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
Public Property
This is a public method
چهار خط اول به دلیل اجرای آبجکت obj$
است که کانستراکتور کلاس Visibility
را فراخوانی کرده است و چهار خط دوم مربوطه به آبجکت child$
است که مجدد منجر به فراخوانی کانستراکتور کلاس Visibility
اما این بار از طریق کلاس ChildClass
شده است و دو خط آخر مرتبط با فراخوانی پراپرتی و متد public
قرارگرفته داخل کلاس Visibility
است که به کلاس ChildClass
به ارث رسیدهاند.
پیش از این گفتیم که گرچه پراپرتیها و متدهای private
فقط و فقط در همان کلاسی که ایجاد شدهاند در دسترس هستند، اما هر چیزی که از جنس protected
باشد علاوه بر همان کلاس، در کلاسها فرزند نیز در دسترس است که برای همین منظور، کدهای فوق را به صورت زیر آپدیت کرده تا این موضوع را تست نماییم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
// echo $obj->publicProperty;
// echo "\n";
// echo $obj->protectedProperty;
// echo "/n";
// echo $obj->privateProperty;
// $obj->showPublicMethod();
// $obj->showProtectedMethod();
// $obj->showPrivateMethod();
$child = new SokanAcademy\ChildClass();
echo $child->publicProperty;
echo "\n";
$child->showPublicMethod();
echo "\n";
echo $child->protectedProperty;
در واقع، سعی نمودهایم تا به پراپرتی protectedProperty$
در کلاس Visibility
که از جنس protected
است دست یابیم اما در خروجی خواهیم داشت:
/var/www/oop/access-modifier$ php index.php
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
Public Property
This is a public method
PHP Fatal error: Uncaught Error: Cannot access protected property SokanAcademy\ChildClass::$protectedProperty in /var/www/oop/access-modifier/index.php:19
Stack trace:
#0 {main}
thrown in /var/www/oop/5-access-modifier/index.php on line 19
میبینیم که در خط نوزدهم به یک ارور برخوردهایم با این مضمون که به پراپرتی protectedProperty$
که داخل کلاس ChildClass
است از داخل فایل index.php
دسترسی نداریم! در واقع، این مشکل از آنجا ناشی میشود که نباید فراموش کنیم که پراپرتیها و متدهای protected
فقط در داخل کلاس فرزند در دسترس هستند و نَه در فایلی که آن کلاس را فراخوانی کردهایم که برای درک بهتر این موضوع، کلاس ChildClass
را به صورت زیر تغییر خواهیم داد:
<?php
namespace SokanAcademy;
class ChildClass extends Visibility
{
public function __construct()
{
echo $this->protectedProperty . "from ChildClass\n";
$this->showProtectedMethod();
}
}
در واقع، داخل کانستراکتور کلاس ChildClass
هم پراپرتی و هم متدی که از جنس protected
بودند را مورد استفاده قرار دادهایم. حال فایل index.php
را به صورت زیر آپدیت میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$obj = new SokanAcademy\Visibility();
// echo $obj->publicProperty;
// echo "\n";
// echo $obj->protectedProperty;
// echo "/n";
// echo $obj->privateProperty;
// $obj->showPublicMethod();
// $obj->showProtectedMethod();
// $obj->showPrivateMethod();
$child = new SokanAcademy\ChildClass();
// echo $child->publicProperty;
// echo "\n";
// $child->showPublicMethod();
// echo "\n";
// echo $child->protectedProperty;
اکنون در خروجی خواهیم داشت:
/var/www/oop/access-modifier$ php index.php
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
Protected Propertyfrom ChildClass
This is a protected method
چهار خط اول مربوط به اجرای کانستراکتور کلاس ChildClass
است که منجر به اجرای کانستراکتور کلاس Visibility
شده است به علاوه این که دو خط آخر نیز حاکی از آنند که از داخل کلاس فرزند به پراپرتیها و متدهای protected
کلاس والد دسترسی داریم.
به عنوان نکتهٔ پایانی این آموزش، مجدد کلاس ChildClass
که به صورت زیر آپدیت شده است را مد نظر قرار میدهیم:
<?php
namespace SokanAcademy;
class ChildClass extends Visibility
{
public function __construct()
{
parent::__construct();
echo $this->protectedProperty . "from ChildClass\n";
$this->showProtectedMethod();
}
}
همانطور که میبینیم، در خط هشتم از کلیدواژهٔ parent
استفاده کرده سپس علائم ::
را درج نموده و در نهایت دستور ()construct__
را نوشتهایم. کاری که این خط از کد انجام میدهد آن است که کانستراکتور کلاس والد که در این مثال Visibility
است را نیز فراخوانی میکند به طوری که از این پس در خروجی خواهیم داشت:
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
The protected property is: Protected Property
The private property is: Private Property
This is a protected method
This is a private method
Protected Propertyfrom ChildClass
This is a protected method
در تفسیر خروجی فوق میتوان گفت که خطوط اول تا چهارم مرتبط با اجرای کانستراکتور کلاس Visibility
است؛ خطوط پنجم تا هشتم مربوط به اجرای بخشی از کدهای کانستراکتور کلاس ChildClass
است که از کلاس والدش به ارث برده است و دو خط آخر نیز اختصاصی کانستراکتور کلاس ChildClass
هستند.
جمعبندی
در این آموزش به بررسی مفهوم Access Modifier در زبان برنامهنویسی پیاچپی پرداختیم و دیدیم که سطوح دسترسی protected
،public
و private
چگونه میتوانند منجر به ایجاد محدودیت در نحوهٔ دستیابی به پراپرتیها و متدهای نوشتهشده داخل یک کلاس گردند مضاف بر این که دیدیم در مبحث وراثت نیز چگونه میتوانند مورد استفاده قرار گیرند.