پس از پوشش دادن مقولهٔ Interface در آموزش گذشته، در این آموزش قصد داریم به بررسی کلاسهایی از جنس Abstract بپردازیم این امکان را در اختیار توسعهدهندگان قرار میدهد تا ویژگی پالیمورفیزِم (چندریختی) در سَبک برنامهنویسی شیئگرا را عملی سازند.
آنچه در ارتباط با کلاسهای اَبستِرَکت میباید مد نظر داشت این است که این دست کلاسها عملکردی همچون اینترفیس دارند با این تفاوت که علاوه بر تعریف متدهایی که صرفاً حاوی شناسه هستند، همچنین میتوان متدهایی نیز داخل آنها تعریف نمود که همچون یک متد معمولی، داخل بدنهٔ متد نیز الگوریتم مد نظر پیادهسازی شده است.
هشدار کلاسهای اَبستِرَکت حتماً میباید حاوی یک متد از جنس abstract باشند که در غیر این صورت به ارور برخواهیم خورد.نکتهٔ دیگری که در ارتباط با کلاسهای اَبستِرَکت وجود دارد این است که از روی کلاسهایی از این جنس هرگز نمیتوان آبجکت ساخت بلکه صرفاً میتوان از آنها در کلاسهای دیگر ارثبری کرد. بالتبع، کلاسی که از یک کلاس اَبستِرَکت ارثبری میکند میباید کلیهٔ متدهای abstract نوشتهشده داخل آن را پیادهسازی نماید.
برای آن که به طور عملی با سازوکار کلاسهای اَبستِرَکت آشنا شویم، داخل پوشهٔ oop
پروژهای تحت عنوان abstract-class
ساخته سپس ساختار فولدرهایی که در این سری از آموزشها مورد استفاده قرار دادهایم را داخل آن ایجاد میکنیم. برای شروع، به داخل پوشهٔ classes
رفته و فایلی تحت عنوان AbstractClass.php
حاوی کدهای زیر میسازیم:
<?php
namespace SokanAcademy;
abstract class AbstractClass
{
public function __construct()
{
echo "This is the constructor the the AbstractClass.";
}
abstract public function anAbstractMethod();
public function doSomething()
{
return "This method is to do something.";
}
}
تفاوتی که ساخت کلاسهایی از جنس اَبستِرَکت با کلاسهای معمولی دارا میباشد در این است که پیش از درج کیورد class
میباید کیورد abstract
را نوشته سپس نامی برای کلاس خود انتخاب کرد. داخل بدنهٔ کلاس AbstractClass
ابتدا یک کانستراکتور سپس دو متد داریم که متد ()anAbstractMethod
همچون متدهایی که داخل اینترفیسها میسازیم صرفاً حاوی یک شناسه میباشد و متد دوم ساختاری همچون متدهای معمولی دارا است. پیش از این گفتیم که هر کلاسی که اَبستِرَکت باشد، حتماً میباید حاوی یک متد از جنس اَبستِرَکت باشد که در همین راستا، متد ()anAbstractMethod
را با درج کیورد abstract
مناسب این کار ساختهایم. حال نوبت به استفاده از این کلاس میرسد که برای این منظور، فایلی تحت عنوان User.php
ساخته و آن را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User extends AbstractClass
{
}
همانطور که در آموزش آشنایی با مفهوم وراثت در زبان PHP دیدیم، برای ارثبری از کلاس اَبستِرَکتی که ایجاد کردیم، ابتدا کیورد extends
را نوشته سپس نام کلاس AbstractClass
را آوردهایم. حال به فایل index.php
رفته و آن را به صورت زیر تکمیل میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
میبینیم که آبجکتی تحت عنوان user$
از روی کلاس User
ساختهایم که با اجرای این فایل، در خروجی خواهیم داشت:
/var/www/oop/abstract-class$ php index.php
PHP Fatal error: Class SokanAcademy\User contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (SokanAcademy\AbstractClass:
:anAbstractMethod) in /var/www/oop/abstract-class/classes/User.php on line 4
با متن اروری مواجه میشویم که حاکی از آن است که داخل کلاس والدِ AbstractClass
یک متد از جنس abstract
وجود دارد که حتماً در کلاس فرزند میباید این متد را پیادهسازی نمود که برای رفع این ارور، مجدد به کلاس User
بازگشته و آن را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User extends AbstractClass
{
public function anAbstractMethod()
{
return "This is the abstract method implemented in the User class.";
}
}
اکنون اگر مجدد فایل index.php
را اجرا کنیم، خواهیم دید که ارور رفع شده است و صرفاً دستوری اجرا میگردد که داخل کانستراکتور کلاس AbstractClass
قرار داشت:
/var/www/oop/8-abstract-class$ php index.php
This is the constructor the the AbstractClass.
همچنین به منظور دستیابی به متدهای داخل کلاس User
نیز میتوان به صورت زیر عمل کرد:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
echo "\n";
echo $user->anAbstractMethod();
echo "\n";
echo $user->doSomething();
که در خروجی نیز خواهیم داشت:
/var/www/oop/abstract-class$ php index.php
This is the constructor the the AbstractClass.
This is the abstract method implemented in the User class.
This method is to do something.
در حقیقت، هم به متد اَبستِرَکت داخل کلاس AbstractClass
تحت عنوان ()anAbstractMethod
دسترسی داریم که در کلاس User
آن را پیادهسازی نمودیم و هم به متد ()doSomething
که بدون نوشتن مجدد آن در کلاس User
به آن دسترسی داریم اما در عین توجه داشته باشیم که میتوان این متد را مجدد در کلاس فرزند به صورت زیر اُورراید نمود:
<?php
namespace SokanAcademy;
class User extends AbstractClass
{
public function anAbstractMethod()
{
return "This is the abstract method implemented in the User class.";
}
public function doSomething()
{
return "This method is overridden in the User class.";
}
}
همانطور که ملاحظه میشود، متد ()doSomething
که به صورت کامل داخل کلاس AbstractClass
تعریف شده بود را مجدد داخل کلاس فرزندِ User
نوشته و چیزی که ریترن میکند را تغییر دادهایم؛ به عبارتی، این متد اُورراید شده است به طوری که اگر مجدد فایل index.php
را اجرا کنیم، در خروجی خواهیم داشت:
/var/www/oop/abstract-class$ php index.php
This is the constructor the the AbstractClass.
This is the abstract method implemented in the User class.
This method is overridden in the User class.
همچنین به خاطر داشته باشیم که داخل کلاسهایی از جنس اَبستِرَکت میتوان پراپرتی هم داشت به طوری که از این پس داخل کلاس AbstractClass
خواهیم داشت:
<?php
namespace SokanAcademy;
abstract class AbstractClass
{
protected $sampleProperty = "This is a property in the AbstractClass.";
public function __construct()
{
echo "This is the constructor the the AbstractClass.";
}
abstract public function anAbstractMethod();
public function doSomething()
{
return "This method is to do something.";
}
}
میبینیم که یک پراپرتی از جنس protected
تحت عنوان sampleProperty$
ساختهایم که دارای یک مقدار پیشفرض است. حال مجدد به کلاس User
بازگشته و آن را به صورت زیر آپدیت میکنیم:
<?php
namespace SokanAcademy;
class User extends AbstractClass
{
public function anAbstractMethod()
{
return "This is the abstract method implemented in the User class.";
}
public function doSomething()
{
return "This method is overridden in the User class.";
}
public function getPropertyValue()
{
return $this->sampleProperty;
}
}
یک متد تحت عنوان ()getPropertyValue
ساختهایم که در متودولوژی شیئگرایی اصطلاحاً به آن متدِ Getter گفته میشود و داخل آن مقدار پراپرتی sampleProperty$
را ریترن کردهایم و جهت تست این متد، به فایل index.php
رجوع کرده و آن را به صورت زیر تغییر میدهیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
echo "\n";
echo $user->anAbstractMethod();
echo "\n";
echo $user->doSomething();
echo "\n";
echo $user->getPropertyValue();
میبینیم که به سادگی این متد را فراخوانی کردهایم به طوری که در خروجی خواهیم داشت:
/var/www/oop/abstract-class$ php index.php
This is the constructor the the AbstractClass.
This is the abstract method implemented in the User class.
This method is overridden in the User class.
This is a property in the AbstractClass.
اساساً در OOP دو اصطلاح داریم تحت عناوین Setter و Getter که در مثال فوق یک نمونه از آنها را مشاهده کردیم اما به منظور ارائهٔ توضیحات بیشتر، در آموزش بعد این مفاهیم را در قالب مثالهای کاربردیتر مورد بررسی بیشتر قرار خواهیم داد.