واجهات الكائنات في PHP
تتيح واجهات الكائنات إنشاء شيفرة تحدّد التوابع التي يجب أن يتضمّنها الصنف دون الحاجة إلى تعريف آلية التحكّم في هذه التوابع.
تعرّف الواجهات بنفس طريقة تعريف الأصناف، ولكن باستخدام الكلمة المفتاحية interface بدل الكلمة المفتاحية class ودون تعريف محتوى أيّ تابعٍ في الواجهة.
يجب أن تكون جميع التوابع المصرّح عنها في الواجهة من النوع public وهذه هي طبيعة الواجهة.
يمكن التصريح عن تابع بانٍ في الواجهة، وهو أمر مفيد في بعض الحالات، كاستخدام التابع من قبل المعامل factories.
العامل implements
يستخدم العامل implements
لتنفيذ الواجهة. يجب تنفيذ جميع التوابع الموجودة في الواجهة ضمن الصنف، وعدم تحقيق ذلك سيؤدي إلى حصول خطأ من نوع fatal. يمكن للأصناف أن تنفّذ (implements) أكثر من واجهة حسب الحاجة وذلك بفصل كل واجهة عن الأخرى بعلامة الفاصلة (,
).
ملاحظة: قبل الإصدار 5.3.9 لم يكن بإمكان الصنف أن يستخدم واجهتين تقرّان تابعين يحملان الاسم ذاته وذلك تجنّبًا لوقوع اللبس، أما الإصدارات الأحدث من اللغة فتسمح بحدوث ذلك ما دام التابعان يحملان التوقيع ذاته.
ملاحظة: يمكن توسيع الواجهات كما هو الحال مع الأصناف وذلك باستخدام العامل extends
.
ملاحظة: يجب أن يستخدم الصنف الذي ينفّذ واجهة معيّنة تواقيع التوابع ذاتها المعرّفة في الواجهة، وخلا ذلك سيحدث خطأ من نوع fatal.
الثوابت
يمكن استخدام الثوابت مع الواجهات، وهي مشابهة لثوابت الأصناف باستثناء أنّه لا يمكن التجاوز عليها (أي إعادة تعريفها) بواسط الصنف أو الواجهة التي ترثها.
أمثلة
المثال 1: مثال على استخدام الواجهة
<?php
// Declare the interface 'iTemplate'
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// تنفيذ الواجهة
// هذه الشيفرة ستعمل
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
}
// هذه الشيفرة لن تعمل
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}
?>
المثال 2: واجهات قابلة للتوسع
<?php
interface a
{
public function foo();
}
interface b extends a
{
public function baz(Baz $baz);
}
// هذه الشيفرة ستعمل
class c implements b
{
public function foo()
{
}
public function baz(Baz $baz)
{
}
}
// هذه الشيفرة لن تعمل وستتسبب في وقوع خطأ
class d implements b
{
public function foo()
{
}
public function baz(Foo $foo)
{
}
}
?>
المثال 3: الوراثة من واجهات متعددة
<?php
interface a
{
public function foo();
}
interface b
{
public function bar();
}
interface c extends a, b
{
public function baz();
}
class d implements c
{
public function foo()
{
}
public function bar()
{
}
public function baz()
{
}
}
?>
المثال 4: استخدام الثوابت مع الواجهات
<?php
interface a
{
const b = 'Interface constant';
}
// Prints: Interface constant
echo a::b;
// لن تعمل هذه الشيفرة لأنّه لا يمكن التجاوز على الثوابت
class b implements a
{
const b = 'Class constant';
}
?>
تقدّم الواجهة وميزة التلميح عن النوع type-hinting طريقة جيدة لضمان أن كائنًا معيّنًا يتضمن توابع محدّدة. راجع العامل instanceof
والتلميح عن النوع.