در آموزش آشنایی با مفهوم 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 داخل هستهٔ زبان پیاچپی را مورد استفاده قرار داد.