38
تشکر

Interface در PHP

PHP – پی اچ پی

PHP – پی اچ پی

یکی از مباحث شی گرایی در زبان‌های برنامه نویسی مبحث Interfaceها است. interface ممکن است در نگاه اول چندان ارزشی برای ما نداشته باشد و ما ممکن است نتوانیم استفاده‌ایی در خور توجه از آن بکنیم. اما در این مطلب میخواهیم نگاه دقیقتری به interfaceها داشته باشیم، مخصوصا در زبان PHP، که البته پایه interfaceها در تمام زبان‌ها مشابه است و فقط syntax آن تفاوت دارد.

Interface چیست؟

interface مانند یک استاندارد عمل میکند. به این صورت که شما میتوانید با استفاده از interface استاندارد پایه‌ایی برای یک نوع از classها تعریف کنید.

برای مثال میخواهیم یک کلاس برای کار با نوع داده Customer ایجاد کنیم، مطمئنا این کلاس دارای یکسری متدهای اصلی است که میخواهیم هر نوع کلاسی که برای کار با نوع داده Customer ساخته میشود دارای این متدهای اصلی باشد، برای اینکار این متدهای اصلی را درون interface تعریف میکنیم.

برای مثال نوع داده Customer ما دارای سه متد اصلی setId و getName و sendMessage است، پس interface ما مشابه زیر میشود.

interface CustomerInterface
{
    public function setId($id);

    public function getName();

    public function sendMessage($title, $content, $flags);
}

نکته یک: در interface نمی‌توان body یا محتویات متدها را تعریف کرد و فقط باید اسم متد و نوع و تعداد پارامترهای ورودی آن را تعریف کرد.

نکته دو: در interface نمیتوان property یا مشخصه تعریف کرد.

حالا تنها کافیست که کلاس‌هایی که برای کار با نوع داده Customer ساخته می‌شوند این interface را implement یا به اصطلاح برآورده کنند. به صورت زیر:

class Customer implements CustomerInterface
{

}

اگر کلاس Customer بالا را اجرا کنیم با خطای Fatal Error مواجه میشویم، زیرا ما CustomerInterface را درون کلاس Customer برآورده یا implement کردیم در حالی که متدهای تعریف شده در interface را نساخته‌اییم. پس زمانی که یک کلاس، یک اینترفیس را implement میکند باید تمام متدهای تعریف شده در interface را تعریف کند.

class Customer implements CustomerInterface
{

    public function setId($id)
    {

    }

    public function getName()
    {

    }

    public function sendMessage($title, $content, $flags)
    {

    }
}

نکته یک: نمی‌توان نوع و تعداد پارامترهای تعریف شده در interface را در classیی که آن را implement کرده است تغییر داد.

نکته دو: اتفاقاتی که درون متدها می‌افتد برای interface مهم نیست، تنها باید وجود داشته باشند.

چرا interface

حالا به درستی از interface استفاده کردیم. اما اینکار چه فایده‌ایی داشت؟ خب خودمان میدانیم که کدام متدها برای کلاس ضروری هستند، چرا باید فایل‌ها و زمان اضافی را برای تولید interface هدر بدهیم؟

استفاده از interface بیشتر برای پروژه‌هایی مناسب است که بیشتر از یک نفر روی آن کار میکند، اما همیشه اینطور نیست.

این شرایط را در نظر بگیرید: من یک کلاس دیگر هم به نام Order دارم که در این کلاس با Customer ارتباط مستقیم داریم به صورتی که زمان ساخت یک شی از کلاس Order، باید یک شی از کلاس Customer به آن بدهیم. خب اینکار را به صورت معمولی (در صورت استفاده نکردن از interface) میتوان به صورت زیر پیاده‌سازی کرد.

class Order
{
    public function __construct(Customer $customer)
    {

    }
}

اما این روش یک مشکل اساسی دارد، آن هم اینکه ما درست کار کردن کلاس Order را منوط به کلاس Customer کردیم، و هیچ کلاس دیگری را نمی‌توان به Order، به عنوان کلاس Customer داد. اما اگر کلاس Order را به صورت زیر پیاده‌سازی کنیم، میتوانیم هر نوع کلاسی را به کلاس Order بدهیم، فقط کافیست آن کلاس، اینترفیس CustomerInterface را implement کرده باشد.

class Order
{
    public function __construct(CustomerInterface $customer)
    {

    }
}

چرا extend نکنیم

در اینجا یک سوال پیش می‌آید که چرا ما یک کلاس به عنوان کلاس پایه با نام Customer نسازیم و تمام کلاس‌هایی که میخواهند با نوع داده Customer کار کنند از این کلاس extend نشوند؟

این شرایط را در نظر بگیرید: حالا ما یک کلاس دیگر با نام Auth داریم که برای کار با این کلاس باید نوع داده User به آن داده شود، در حالی که نوع داده User میتواند انواع مختلفی مانند Customer و Admin داشته باشد و ما نباید این کلاس را محدود به نوع User خاصی بکنیم.

برای پیاده‌سازی این شرایط به راحتی میتوان یک interface جدید برای نوع داده User ساخت و کلاس Customer به جای اینکه تنها اینترفیس CustomerInterface را implement کند، دو اینترفیس CustomerInterface و UserInterface را implement می‌کند.

بنابراین کل کدهای ما به صورت زیر میشود.


نتیجه‌گیری

یک مثال بهتر برای interfaceها کار با Driverها است. برای مثال شما با پنل‌های SMS زیادی در برنامه کار میکنید، اما میخواهید به تمام این پنل‌ها تنها با یک کلاس دسترسی داشته باشید، در این روش میتوان یک interface برای یک پنل SMS پایه درست کرد که تمام کلاس‌های دیگر، آن را implement کنند.

در این بین شاید به یک سوال دیگر هم پاسخ داده باشیم، آن هم استفاده از کلاس abstract به جای interface است. از abstract نمی‌توان به جای interface استفاده کرد زیرا یک کلاس نمی‌تواند از چندین کلاس extend شود در حالی که می‌تواند چندین interface را implement کند.

  • محمد می‌گه:

    سلام چون نظرات مطلبی ک میخوام بگم بسته شده اینجا میگم
    امید وارم اقای شفیعی و دوستان پاسخ حقیر رو بفرمایید

    مربوط به ریسپانسیو کردن هست
    مشکل من درقسمت
    href
    هست گه عمل نمیکنه!چطور باید ادرس دهی کنم؟شما در اون قسمت جلوی اچرف رو خالی گذاشتید
    با تک کوتیشن و دبل کوتیشن هم امتحان کردم جواب نداد خواهش میکنم کمکم کنید

  • جواد مجرد می‌گه:

    خیلی عالی بود مطلب. کدهایی که نوشتید خیلی بهم کمک کرد. توی پروژه‌ام بهش خیلی نیاز داشتم.

  • به جای همه ی اینها میشه از trait استفاده کرد خیلی هم ساده تر و بهتره مثل یه include عمل میکنه

  • محسن شفیعی می‌گه:

    دوستان، نسخه اولیه مشارکت در آپارنت راه‌اندازی شده. به صفحه کاربری مراجعه کنید.
    ممنون


  • نظرات این مطلب بسته است.