در آموزش آشنایی با مفهوم OOP و بررسی اصول چهارگانهٔ شیئگرایی گفتیم که یکی از اصول کلیدی این متودولوژی Polymorphism است بدان معنا که یک کلاس میتواند به اَشکال مختلفی نمودِ عینی پیدا کند و برای برخورداری از این قابلیت، نیاز است تا با مفاهیمی همچون Interface و Abstract Class آشنا شویم که مورد اول را در این آموزش و مورد دوم را در آموزش بعد مورد بررسی قرار خواهیم داد. در واقع، در پاسخ به این پرسش که «اینترفیس چیست؟» میتوان گفت که اینترفیس همچون یک سندی است که مشخص میکند کلاسهایی که از آن استفاده میکنند میباید حاوی چه متدهایی باشند مضاف بر این که اینترفیسها این امکان را در اختیار توسعهدهندگان میگذارند تا این اطمینان حاصل گردد که برخی کلاسهای پروژه از ساختاری واحد تبعیت میکنند.
به منظور درک بهتر مفهوم اینترفیس، داخل پوشهٔ oop پروژهای تحت عنوان interface میسازیم و داخل پوشهٔ classes فایلی با نامی دلخواه همچون SampleInterface.php ساخته و کدهای زیر را داخل آن مینویسیم:
<?php
namespace SokanAcademy;
interface SampleInterface
{
public function showFirstName();
public function showLastName();
public function showFullName();
}
همانطور که میبینیم، پیش از هر چیز نِیماِسپیس این فایل را مشخص ساختهایم سپس به منظور ساخت یک اینترفیس در زبان برنامهنویسی پیاچپی از کیورد interface استفاده کرده سپس نامی دلخواه همچون SampleInterface برایش در نظر میگیریم که میباید این نام با نام فایل مذکور یکسان باشد. داخل بدنهٔ این اینترفیس که ساختاری همچون یک کلاس دارا است، سه متد تعریف کردهایم با این توضیح که متدهای مذکور فقط و فقط دارای یک شناسه هستند و از هیچ بدنهای که بتوان داخل آن کدی را نوشت برخوردار نمیباشند که در ظاهر ممکن است کمی عجیب به نظر برسد!
در ادامه، داخل پوشهٔ classes فایلی به نام User.php ساخته و کدهای زیر را داخل آن مینویسیم و خواهیم دید که چگونه میتوان از اینترفیس فوق در آن استفاده نمود:
<?php
namespace SokanAcademy;
class User implements SampleInterface
{
}
همانطور که میبینیم، چنانچه بخواهیم کلاسی را موظف به تبعیت از یک اینترفیس نماییم، میباید پس از نام انتخابی برای کلاس خود از کلیدواژهٔ implements استفاده نموده سپس نام اینترفیس مد نظر را بیارویم. در واقع، از این لحظه به بعد کلاس User را موظف ساختهایم تا از ساختار تعریفشده داخل اینترفیس SampleInterface پیروی کند. جهت تست این کلاس، وارد فایل index.php شده و آبجکتی از روی این کلاس داخل این فایل میسازیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
در صورت اجرای فایل فوق شاهد خروجی زیر خواهیم بود:
/var/www/oop/7-interface$ php index.php
PHP Fatal error: Class SokanAcademy\User contains 3 abstract methods and must therefore be declared abstract or implement the remaining methods (SokanAcademy\SampleInterfa
ce::showFirstName, SokanAcademy\SampleInterface::showLastName, SokanAcademy\SampleInterface::showFullName) in /var/www/oop/interface/classes/User.php on line 4
متن این ارور حاکی از آن است که اینترفیسِ SampleInterface حاوی سه متد است که هر سه میباید داخل کلاس User که از این اینترفیس ایمپلیمنت میکند تعریف شوند اما این کار صورت نگرفته است که برای رفع این ارور، کلاس User را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User implements SampleInterface
{
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
}
اکنون اگر فایل index.php را مجدد اجرا کنیم، خواهیم دید که ارور مرتفع شده است. در واقع، کاری که داخل کلاس User انجام دادهایم آن است که این کلاس را موظف به تبعیت از ساختار اینترفیس SampleInterface کردهایم و از آنجا که این اینترفیس میگوید سه متد ()showFirstName و ()showLastName و همچنین متد ()showFullName را میباید داخل کلاسی که از این اینترفیس ایمپلیمنت میشود داشته باشیم، داخل کلاس User این متدها را نوشته سپس داخل بدنهٔ آنها نیز دستور سادهای را درج نمودهایم.
در حقیقت، اگر کلاس دیگری مثلاً تحت عنوان User2 داشته باشیم و آن هم از اینترفیس SampleInterface ایمپلیمنت کند، این تضمین ایجاد میگردد که هر دو کلاس User و User2 از ساختاری یکسان برخوردار خواهند بود اما در عین حال هر کدام میتوانند پیادهسازی مخصوص به خود را داشته باشند که این کار به نوعی مرتبط با ویژگی Polymorphism است.
همچنین لازم به یادآوری است که استفاده از اینترفیسها در پروژههایی که به صورت تیمی توسعه پیدا میکنند راهگشا خواهد بود چرا که اگر گروهی روی کلاس User کار کنند و گروهی دیگر روی کلاس User2، این تضمین داده میشود که هر دو گروه از دولوپرها ساختاری یکسان را دنبال میکنند و این کار به هر چه استانداردتر شدن پروژه کمک میکند.
آنچه در ارتباط با کلاس و اینترفیس وجود دارد این است که یک کلاس نمیتواند از بیش از یک کلاس ارثبری کند اما در عین حال یک کلاس میتواند از بیش از یک اینترفیس ایمپلیمنت کند. برای درک بهتر این موضوع، فایل دیگری داخل پوشهٔ classes تحت عنوان UserInterface.php ساخته و کدهای زیر را داخل آن مینویسیم:
<?php
namespace SokanAcademy;
interface UserInterface
{
public function showUsername();
}
طبق آنچه پیش از این آموختیم، اینترفیسی تحت عنوان UserInterface ساخته که صرفاً حاوی متد ()showUsername است. حال طبق روال زیر، داخل کلاس User از این اینترفیس نیز استفاده خواهیم کرد:
<?php
namespace SokanAcademy;
class User implements SampleInterface, UserInterface
{
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
}
در واقع، پس از نام اینترفیس SampleInterface یک علامت , قرار داده سپس نام اینترفیس UserInterface را نوشتهایم و به همین ترتیب به هر تعداد که بخواهیم میتوانیم از اینترفیسهای مختلف استفاده کنیم. حال اگر فایل index.php را اجرا کنیم خواهیم داشت:
/var/www/oop/interface$ 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\UserInterface:
:showUsername) in /var/www/oop/interface/classes/User.php on line 4
میبینیم که همچون مورد قبل، مفسر پیاچپی از ما ایراد میگیرد که از اینترفیسی تحت عنوان UserInterface داخل کلاس User استفاده کرده اما متد ()showUsername را داخل این کلاس تعریف نکردهایم که برای رفع این ارور، کلاس User را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User implements SampleInterface, UserInterface
{
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
public function showUsername()
{
return "This method is to show the username.";
}
}
که در این صورت اگر فایل index.php را مجدد اجرا کنیم، هیچ گونه اروری دریافت نخواهیم کرد.
آشنایی با برخی اینترفیسهای موجود در هستهٔ زبان PHP
جهت سهولت کار، طراحان زبان برنامهنویسی پیاچپی اقدام به تعریف یک سری اینترفیس پیشفرض کردهاند که به سادگی قابل استفاده هستند که از آن جمله میتوان به Countable و JsonSerializable اشاره کرد که به ترتیب حاوی متدهای ()count و ()jsonSerialize هستند. جهت استفاده از این اینترفیسهای پیشفرض، کلاس User را به شکل زیر آپدیت میکنیم:
<?php
namespace SokanAcademy;
class User implements SampleInterface, UserInterface, Countable, JsonSerializable
{
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
public function showUsername()
{
return "This method is to show the username.";
}
}
میبینیم که طبق روال گذشته این دو اینترفیس را نیز ایمپلیمنت نمودهایم اما چنانچه فایل index.php را اجرا کنیم، به عنوان خروجی خواهیم داشت:
/var/www/oop/interface$ php index.php
PHP Fatal error: Interface 'SokanAcademy\Countable' not found in /var/www/oop/interface/classes/User.php on line 4
این ارور حاکی از آن است که اینترفیس Countable تشخیص داده نشده است و بالتبع همین ارور برای JsonSerializable نیز رخ خواهد داد اما از آنجا که ارور اول منجر به توقف نمایش سایر ارورها شده است، آن را ملاحظه نمیکنیم. در حقیقت، این ارور به نوعی مرتبط با نِیماِسپیس این فایل است. همانطور که میبینیم، این فایل دارای نِیماِسپیس SokanAcademy است و این در حالی است که اینترفیسهای Countable و JsonSerializable و حتی دیگر کلاسهای موجود داخل هستهٔ زبان پیاچپی همچون PDO و غیره دارای یک اصطلاحاً اِسکوپ سراسری هستند و داخل فایلی که هیچ گونه نِیماِسپیسی ندارد به سادگی میتوان آنها را مورد استفاده قرار داد اما زمانی که از این اینترفیسها و کلاسها داخل یک فایلی استفاده میکنیم که حاوی نِیماِسپیس است، میباید قبل از نام آنها از علامت \ استفاده کرد به طوری که داریم:
<?php
namespace SokanAcademy;
class User implements SampleInterface, UserInterface, \Countable, \JsonSerializable
{
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
public function showUsername()
{
return "This method is to show the username.";
}
}
در صورت اجرای مجدد فایل index.php خواهیم داشت:
/var/www/oop/interface$ php index.php
PHP Fatal error: Class SokanAcademy\User contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Countable::count, JsonSeri
alizable::jsonSerialize) in /var/www/oop/interface/classes/User.php on line 4
گرچه مجدد ارور دریافت کردیم، اما این بار محتوای ارور متفاوت بوده و حاکی از آن است که داخل این کلاس از دو اینترفیس Countable و JsonSerializable استفاده کردهایم که به ترتیب حاوی متدهای ()count و ()jsonSerialize میباشند که با اضافه نمودن این متدها، ارور فوق مرتفع خواهد شد اما پیش از انجام این کار، نیاز به توضیح است که با درج علامت \ قبل از نام این اینترفیسها به مفسر پیاچپی دستور میدهیم که نِیماِسپیس این فایل را مبنا قرار نداده بلکه اِسکوپ سراسری پیاچپی را مبنا قرار داده و این اینترفیسها را از آنجا لود کند. حال کلاس User را به صورت زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User implements SampleInterface, UserInterface, \Countable, \JsonSerializable
{
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
public function showUsername()
{
return "This method is to show the username.";
}
public function count()
{
// some code
}
public function jsonSerialize()
{
// some code
}
}
در این مرحله از کار اگر مجدد فایل index.php را اجرا کنیم، به هیچ گونه اروری برنخواهیم خورد. در ارتباط با این دو متدی که تعریف نمودیم، میتوان از فانکشنهایی همچون ()count و ()json_encode به منظور تکمیل متدهایی که جدید اضافه نمودیم استفاده نماییم که برای روشنتر شدن نحوهٔ انجام این کار، کلاس User را به شکل زیر تکمیل میکنیم:
<?php
namespace SokanAcademy;
class User implements SampleInterface, UserInterface, \Countable, \JsonSerializable
{
public $userProperties = ['firstname' => 'behzad', 'lastname' => 'moradi', 'dob' => 1362];
public function showFirstName()
{
return "This method is to show the firstname.";
}
public function showLastName()
{
return "This method is to show the lastname.";
}
public function showFullName()
{
return "This method is to show the fullname.";
}
public function showUsername()
{
return "This method is to show the username.";
}
public function count()
{
return count($this->userProperties);
}
public function jsonSerialize()
{
return json_encode($this->userProperties);
}
}
داخل بدنهٔ این کلاس یک پراپرتی از جنس آرایه تحت عنوان userProperties$ ساخته و مقداری پیشفرض نیز برای آن در نظر گرفتهایم سپس داخل متد ()count که مرتبط با اینترفیس Countable است از متدی به اصطلاح Built-in در زبان پیاچپی تحت عنوان ()count استفاده کرده که یک پارامتر ورودی از جنس آرایه گرفته و تعدا اِلِمانهای آن را بازمیگرداند. همچنین داخل متد ()jsonSerialize که برگرفته از اینترفیس JsonSerializable میباشد از فانکشن ()json_encode استفاده کرده که این وظیفه را دارا است تا آرایهای که به عنوان پارامتر ورودی میگیرد را در قالب فرمت جیسون ریترن کند. حال فایل index.php را به صورت زیر تکمیل میکنیم:
<?php
ini_set('display_errors', '1');
require_once 'vendor/autoload.php';
$user = new SokanAcademy\User();
echo $user->count();
echo "\n";
echo $user->jsonSerialize();
تنها کاری که کردهایم این است که متدهای ()count و ()jsonSerialize کلاس مذکور را فراخوانی کردهایم به طوری که در خروجی نیز خواهیم داشت:
/var/www/oop/7-interface$ php index.php
3
{"firstname":"behzad","lastname":"moradi","dob":1362}
میبینیم که ابتدا تعداد اِلِمانهای پراپرتی userProperties$ چاپ شده سپس محتویات این پراپرتی در فرمت جیسون چاپ گردیدهاند.
جمعبندی
در مبحث شیئگرایی، یکی از مباحث پرکاربرد چیزی است تحت عنوان اینترفیس و در این آموزش دیدیم که در زبان پیاچپی چگونه میتوانیم اقدام به ساخت یک اینترفیس سپس استفاده از آن داخل کلاسهای مختلف نمود. همچنین به بررسی این موضوع پرداختیم که به چه شکل میتوان اینترفیسهای به اصطلاح Built-in داخل هستهٔ زبان پیاچپی را مورد استفاده قرار داد.
