Skip to content

6. الواجهات

الواجهة هي بنية تحدد نماذج أولية للطرق. يجب على الفئة التي تنفذ واجهة ما أن تحدد الكود لجميع طرق الواجهة.

6.1. شجرة البرامج النصية

Image

6.2. الواجهة الأولى

نحدد واجهة [IExample] في نص برمجي [IExample.php]. في هذا النص البرمجي نفسه، نحدد فئتين تنفذان واجهة [IExample]:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// namespace
namespace Exemples;
 
// an interface
interface IExemple {
    // interface methods
    public function ajouter(int $i, int $j): int;
    public function soustraire(int $i, int $j): int;
}
 
// implementation 1 of the IExemple interface
class Classe1 implements IExemple {
    public function ajouter(int $a, int $b): int {
        return $a + $b + 10;
    }
 
    public function soustraire(int $a, int $b): int {
        return $a - $b + 20;
    }
 
}
 
// implementation 2 of the IExemple interface
class Classe2 implements IExemple {
    public function ajouter(int $a, int $b) : int{
        return $a + $b + 100;
    }
 
    public function soustraire(int $a, int $b) : int {
        return $a - $b + 200;
    }
 
}

تعليقات

  • الأسطر 10–14: تحدد واجهة IExample طريقتين: دالة add (السطر 12) ودالة subtract (السطر 13). ولا تحدد الواجهة كود هاتين الطريقتين، بل ستقوم الفئات التي تنفذ الواجهة بذلك؛
  • السطر 17: تنفذ الفئة Class1 واجهة IExample. وبالتالي، فإنها تحدد كودًا لطريقة add (السطر 18) وطريقة subtract (السطر 22)؛
  • الأسطر 29-38: الأمر نفسه بالنسبة لفئة Class2؛

نستخدم واجهة [IExemple] في البرنامج النصي [interfaces-01.php] التالي:


<?php
 
require_once "IExemple.php";
use \Exemples\Classe1;
use \Exemples\Classe2;
use \Exemples\IExemple;
 
// function
function calculer(int $a, int $b, IExemple $interface) : void {
  print $interface->ajouter($a, $b)."\n";
  print $interface->soustraire($a, $b)."\n";
}
 
// ------------------- hand
// creation of 2 objects of type Class1 and Class2
$c1 = new Classe1();
$c2 = new Classe2();
// call the calculate function
calculer(4, 3, $c1);
calculer(14, 13, $c2);

تعليقات

  • الأسطر 3–6: تضمين وتعريف الفئات والواجهات التي يستخدمها البرنامج النصي؛
  • السطر 3: بدلاً من عبارة include، استخدمنا هنا عبارة require_once. تضمّن عبارة include ملفًا في البرنامج النصي الحالي حتى لو كان قد تم تضمينه بالفعل، في حين أن عبارة require_once تضمّنه مرة واحدة فقط. لذلك، عندما يتعلق الأمر بتضمين الكود، نفضل عبارة require_once؛
  • الأسطر 9-12: نُعرّف دالة؛
  • السطر 9: هنا، نعلن أنواع المعلمات الثلاثة. إذا لم تكن المعلمة الفعلية من النوع المتوقع أثناء وقت التشغيل، يتم إصدار خطأ. المعلمة الثالثة من النوع [IExample]. هذا يعني أن يجب أن تكون المعلمة الفعلية مثيلًا لفئة تنفذ واجهة [IExample]؛ في مثالنا، هذا يعني مثيلًا لفئتي [Class1] أو [Class2]؛
  • السطران 10-11: نستخدم طرق [add، subtract] الخاصة بواجهة [IExample]؛
  • السطر 19: المعلمة الفعلية الثالثة من النوع [Class1]، وهي متوافقة مع النوع [IExample] للمعلمة الشكلية الثالثة للدالة؛
  • السطر 20: الأمر نفسه بالنسبة لفئة [Class2]؛

النتائج

1
2
3
4
17
21
127
201

6.3. اشتقاق واجهة

تمامًا كما يمكن لفئة فرعية أن تمتد من فئة أصلية، يمكن لواجهة فرعية أن تمتد من واجهة أصلية.

لننظر إلى واجهة [IExample2] المُعرَّفة في ملف [IExample2.php]:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
// namespace
namespace Exemples;
 
// interface definition IExemple included
require_once __DIR__."/IExemple.php";
 
// an interface derived from IExemple
interface IExemple2 extends IExemple {
    // the interface method
    public function multiplier(int $i, int $j): int;
}
 
// implementation of IExemple2 interface
class Classe3 extends Classe2 implements IExemple2 {
   
    public function multiplier(int $a, int $b): int {
        return $a * $b;
    }
 
}

تعليقات

  • السطر 6: ستكون الواجهة [IExample2] في نفس مساحة الاسم مثل الواجهة [Iexample]؛
  • السطر 9: تم تضمين ملف تعريف واجهة [Iexample]؛
  • الأسطر 12-15: تعريف الواجهة [IExample2]، التي تمتد (ترث) من الواجهة [IExample] وتضيف طريقة جديدة إليها (السطر 14)؛
  • الأسطر 18-24: الفئة [Class3] تمتد من الفئة [Class2]. وبما أن [Class2] تنفذ الواجهة [IExample]، فإن [Class3] ستنفذها أيضًا. في الواقع، ترث [Class3] جميع الطرق العامة والمحمية للفئة [Class2]، بما في ذلك طريقتي add و subtract. علاوة على ذلك، نحدد أن [Class3] تنفذ واجهة [IExample2]. وبالتالي، يجب أن تنفذ أيضًا طريقة multiply، التي لا تنفذها [Class2]. وهذا ما تفعله الأسطر 20–22؛

يتم استخدام واجهة [IExample2] بواسطة البرنامج النصي [interfaces-02] التالي:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// inclusion and qualification of classes and interfaces required by the script
require_once __DIR__."/Iexemple2.php";
use \Exemples\IExemple2;
use \Exemples\Classe3;
 
// function
function calculer(int $a, int $b, IExemple2 $interface) {
    print $interface->ajouter($a, $b) . "\n";
    print $interface->soustraire($a, $b) . "\n";
    print $interface->multiplier($a, $b) . "\n";
}
 
// ------------------- hand
// creation of 1 Class3 object implementing IExemple2
$c3 = new Classe3();
// call the calculate function
calculer(4, 3, $c3);

تعليقات

  • السطر 12: المعلمة الثالثة لدالة [calculate] هي من النوع [IExample2]؛
  • الأسطر 13–15: يتم استخدام الطرق الثلاث لواجهة [IExample2]؛
  • السطر 22: يتم استدعاء الدالة [calculate] باستخدام كائن من النوع [IExample2] كمعلمة ثالثة (السطر 20)؛

النتائج

1
2
3
107
201
12

6.4. تمرير واجهة كمعلمة دالة

رأينا في القسم السابق أنه عندما يكون النوع المتوقع لمعلمة الدالة هو فئة، يمكن أن تكون المعلمة الفعلية كائنًا من النوع المتوقع أو نوعًا مشتقًا. وينطبق الأمر نفسه على الواجهات، كما هو موضح في البرنامج النصي التالي [interfaces-03.php]:


<?php
 
// strict adherence to function parameter types
declare(strict_types=1);
 
// inclusion and qualification of classes and interfaces required by the script
require_once __DIR__."/IExemple.php";
use \Exemples\IExemple;
require_once __DIR__."/IExemple2.php";
use \Exemples\Classe3;
 
// function
function calculer(int $a, int $b, IExemple $interface) {
  print $interface->ajouter($a, $b) . "\n";
  print $interface->soustraire($a, $b) . "\n";
}
 
// ------------------- hand
// creation of 1 object of type Class3 which implements IExemple2 and therefore IExemple
$c3 = new Classe3();
// call the calculate function
calculer(4, 3, $c3);

تعليقات

  • السطر 13: تتوقع الدالة [calculate] نوع [IExample] كمعلمة ثالثة لها. وهذا يعني أن نوع المعلمة الفعلي يمكن أن يكون [IExample] أو نوع مشتق؛
  • السطر 20: نقوم بإنشاء مثيل لكائن $c3 من النوع [Class3]، وهي فئة تنفذ الواجهة [IExample2]، التي تمتد بدورها الواجهة [IExample]. لذا، في النهاية، ينفذ $c3 الواجهة [IExample]؛
  • السطر 22: نستدعي الدالة [calculate] باستخدام كائن $c3 من النوع [Class3] كمعلمة ثالثة. من خلال التفاعل بين وراثة الفئات والتنفيذات، رأينا أن الكائن $c3 ينفذ النوع [IExample]. لذلك يمكننا استخدامه كمعلمة ثالثة؛

النتائج

107
201