سرفصل‌های آموزشی
آموزش OOP در PHP
آشنایی با کلاس‌های Abstract در زبان PHP

آشنایی با کلاس‌های Abstract در زبان PHP

پس از پوشش دادن مقولهٔ‌ 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 که در مثال فوق یک نمونه از آن‌ها را مشاهده کردیم اما به منظور ارائهٔ توضیحات بیشتر، در آموزش بعد این مفاهیم را در قالب مثال‌های کاربردی‌تر مورد بررسی بیشتر قرار خواهیم داد.

online-support-icon