مقدمة إلى Generics في PHP: ما هي ولماذا تحتاجها
إذا كنت قد بدأت للتو في تعلم PHP أو كنت تكتب به لبعض الوقت، فمن المحتمل أنك واجهت موقفًا حيث تحتاج دالة أو كلاس إلى العمل مع أنواع بيانات مختلفة. على سبيل المثال، تقوم بإنشاء مجموعة يمكنها تخزين الأرقام والسلاسل والكائنات. بدون Generics (الأنواع العامة)، سيتعين عليك إما كتابة كلاسات منفصلة لكل نوع، أو استخدام أنواع مختلطة (mixed)، مما يقلل من أمان الكود.
Generics هي آلية تسمح بإنشاء كلاسات وواجهات ودوال تعمل مع أنواع بيانات مختلفة مع الحفاظ على كتابة صارمة للأنواع. ظهر دعم Generics في PHP بدءًا من الإصدار 8.0، وتم تحسينه بشكل كبير في PHP 8.1 و 8.2. في هذه المقالة، سنشرح لماذا تحتاجها، وكيفية استخدامها، وما هي المزايا التي تقدمها.
لماذا تحتاج Generics في PHP؟
مشكلة عدم وجود أنواع عامة
تخيل أنك تكتب كلاسًا للتعامل مع قائمة من العناصر. بدون Generics، سيتعين عليك استخدام النوع mixed أو كتابة كلاسات منفصلة لكل نوع بيانات:
<?php// بدون Generics — غير آمنclass SimpleList { private array $items = [];
public function add($item): void { $this->items[] = $item; }
public function get(int $index): mixed { return $this->items[$index] ?? null; }}
// الاستخدام$list = new SimpleList();$list->add(42);$list->add('سلسلة'); // لن يحدث خطأ، ولكن المنطق معطل$value = $list->get(0); // النوع mixed — لن تخبرك IDE أن هذا int?>كما ترى، يؤدي هذا النهج إلى أخطاء محتملة: يمكنك إضافة سلسلة عن طريق الخطأ حيث يُتوقع أرقام فقط، ولن تتمكن IDE من تحذيرك من ذلك.
مزايا Generics
- أمان الأنواع: يتحقق المترجم و IDE من تطابق الأنواع في مرحلة كتابة الكود.
- إعادة الاستخدام: كلاس أو دالة واحدة تعمل مع أي أنواع بيانات.
- قراءة الكود: من الواضح فورًا أي الأنواع متوقعة.
- أخطاء أقل: يتم استبعاد عدم تطابق الأنواع العرضي.
مع Generics، يصبح نفس كلاس القائمة آمنًا وعالميًا:
<?php// مع Generics — آمنclass GenericList { private array $items = [];
public function add(T $item): void { $this->items[] = $item; }
public function get(int $index): ?T { return $this->items[$index] ?? null; }}
// الاستخدام$intList = new GenericList();$intList->add(42);// $intList->add('سلسلة'); // خطأ في الأنواع!
$stringList = new GenericList();$stringList->add('مرحبًا');$value = $stringList->get(0); // IDE تعلم أن هذا string?>كيفية استخدام Generics في PHP
الصيغة الأساسية
يتم تعريف Generics في PHP باستخدام الأقواس الزاوية <> والحرف T (من Type) — هذا هو الاسم الشائع لمتغير النوع. يمكنك استخدام أي أسماء، ولكن T هو المعيار.
مثال مع كلاس:
<?phpclass Container { private T $value;
public function __construct(T $value) { $this->value = $value; }
public function getValue(): T { return $this->value; }}
$intContainer = new Container(100);$stringContainer = new Container('Hello');?>قيود الأنواع
في بعض الأحيان، تحتاج أن يتوافق نوع المعلمة مع واجهة أو كلاس معين. لهذا، يتم استخدام القيود (bounds):
<?phpinterface Printable { public function print(): string;}
class Document implements Printable { public function print(): string { return 'مستند'; }