الملخص: ستناقش هذه المقالة مفهوم تعدد الأشكال وتطبيقه في التصميم الموجه للكائنات، كما ستحلل كيفية استخدام تعدد الأشكال في PHP 5 ومزاياه وعيوبه.
تم تنفيذ دعم الربط المتأخر في الإصدارات الأخيرة من PHP. وبطبيعة الحال، لا تزال هناك العديد من المشاكل عند استخدام وظيفة الربط المتأخر. إذا كنت تستخدم إصدارًا أقدم من PHP (يعمل الخادم الخاص بي على PHP 5.0.1)، فقد تجد أن الدعم للربط المتأخر غير متوفر. لذلك، يرجى ملاحظة أن الكود الموجود في هذه المقالة قد لا يعمل في إصدار PHP 5 الخاص بك.
1. PHP 5 وتعدد الأشكال
تود هذه المقالة مناقشة أحد أهم أجزاء البرمجة الشيئية - تصميم تعدد الأشكال. لتوضيح المشكلة، أنا أستخدم PHP 5. قبل مواصلة القراءة، يرجى توضيح أن هذه المقالة لا تتعلق بالكامل بـ PHP. على الرغم من أن اللغة قد قطعت خطوات كبيرة في التطور السريع خلال الإصدارين الرئيسيين السابقين، إلا أن دعم الكائنات لا يزال أمامها بعض الوقت قبل أن تتمكن من منافسة اللغات الأكثر نضجًا مثل دورة C++ أو Java.
إذا كنت مبتدئًا في البرمجة الشيئية، فقد لا تكون هذه المقالة مناسبة لك، لأن هذا الجزء من تعدد الأشكال مميز: بمجرد أن تفهمه، لن تنساه أبدًا. إذا كنت تريد أن تتعلم القليل عن برمجة الكائنات وتصميمها، ولا تعرف تمامًا ما يعنيه عندما يقول شخص ما "الكائن متعدد الأشكال"، فهذه المقالة مخصصة لك.
بنهاية هذه المقالة، يجب أن تعرف ما هو تعدد الأشكال وكيفية تطبيقه على التصميم الموجه للكائنات، وسوف تفهم مزايا وعيوب برمجة الكائنات في PHP 5.
2. ما هو تعدد الأشكال؟
تعريف تعدد الأشكال من موقع Dictionary.com هو "أنه يحدث بأشكال أو مراحل أو أنواع مختلفة في منظمات مستقلة أو في نفس المنظمة دون اختلاف جوهري." من هذا التعريف، يمكننا أن نعتقد أن تعدد الأشكال الجنسية هو طريقة برمجية لوصف الشيء نفسه كائن من خلال حالات أو مراحل متعددة. في الواقع، معناه الحقيقي هو أنه في التطوير الفعلي، نحتاج فقط إلى التركيز على برمجة واجهة أو فئة أساسية، ولا داعي للقلق بشأن الفئة (الفئة) المحددة التي ينتمي إليها الكائن.
إذا كنت على دراية بأنماط التصميم، حتى لو كان لديك فهم أولي فقط، فسوف تفهم هذا المفهوم. في الواقع، قد يكون تعدد الأشكال هو أعظم أداة في برمجة التصميم المبني على الأنماط. فهو يسمح لنا بتنظيم كائنات متشابهة بطريقة منطقية بحيث لا داعي للقلق بشأن نوع الكائن المحدد عند البرمجة؛ علاوة على ذلك، نحتاج فقط إلى برمجة الواجهة المطلوبة أو الفئة الأساسية. كلما كان التطبيق أكثر تجريدًا، أصبح أكثر مرونة - وتعدد الأشكال هو أحد أفضل الطرق لتجريد السلوك.
على سبيل المثال، دعونا نفكر في فئة تسمى "الشخص". يمكننا تصنيف الأشخاص بفئات تسمى ديفيد وتشارلز وأليخاندرو. لدى الشخص طريقة مجردة AcceptFeedback()، ويجب على جميع الفئات الفرعية تنفيذ هذه الطريقة. هذا يعني أن أي كود يستخدم فئة فرعية من فئة الشخص الأساسية يمكنه استدعاء أسلوب AcceptFeedback (). ليس عليك التحقق مما إذا كان الكائن هو ديفيد أم أليخاندرو، فمجرد معرفة أنه شخص يكفي. ونتيجة لذلك، يحتاج الكود الخاص بك فقط إلى التركيز على "القاسم المشترك الأدنى" - فئة الشخص.
يمكن أيضًا إنشاء فئة الشخص في هذا المثال كواجهة. بالطبع هناك بعض الاختلافات مقارنة بما سبق، أهمها: الواجهة لا تعطي أي سلوك، بل تحدد فقط مجموعة من القواعد. تتطلب واجهة الشخص "يجب عليك دعم طريقة AddFeedback()"، بينما يمكن لفئة الشخص توفير بعض التعليمات البرمجية الافتراضية لطريقة AddFeedback() - يمكن أن يكون فهمك لهذا هو "إذا لم تختر دعم AddFeedback()، إذن يجب عليك توفير تطبيق افتراضي. "كيفية اختيار واجهة أو فئة أساسية تتجاوز موضوع هذه المقالة؛ ومع ذلك، بشكل عام، تحتاج إلى تنفيذ طريقة افتراضية من خلال الفئة الأساسية. يمكنك أيضًا استخدام الواجهة إذا كان بإمكانك ببساطة تحديد مجموعة الوظائف المطلوبة التي ينفذها فصلك.
3. تطبيق التصميم متعدد الأشكال
سنستمر في استخدام مثال الفئة الأساسية للشخص، والآن دعونا نحلل التنفيذ غير متعدد الأشكال. تستخدم الأمثلة التالية أنواعًا مختلفة من كائنات الشخص - وهي طريقة برمجة غير مرضية على الإطلاق. لاحظ أنه تم حذف فئة الشخص الفعلية. حتى الآن، كنا مهتمين فقط بمسألة مكالمات الكود.
<?php
$name = $_SESSION['name'];
$myPerson = Person::GetPerson($name);
التبديل (get_class($myPerson)){
حالة "ديفيد":
$myPerson->AddFeedback('مقالة رائعة!', 'بعض القراء', date('Ym-d'));
استراحة؛
حالة "تشارلز":
$myPerson->feedback[] = array('بعض القراء', 'تحرير رائع!');
استراحة؛
حالة "أليخاندرو":
$myPerson->Feedback->Append('Javascript رائع!');
استراحة؛
تقصير :
$myPerson->AddFeedback('Yay!');
}
?>
يوضح هذا المثال كائنات ذات سلوكيات مختلفة، ويتم استخدام عبارة التبديل لتمييز كائنات فئة الشخص المختلفة لتنفيذ العمليات الصحيحة الخاصة بها. لاحظ أن تعليقات التعليقات هنا تختلف باختلاف الظروف. قد لا يكون هذا هو الحال في تطوير التطبيقات الحقيقية؛ فأنا ببساطة أوضح الاختلافات الموجودة في تطبيقات الفصل.
المثال أدناه يستخدم تعدد الأشكال.
<?php
$name = $_SESSION['name'];
$myPerson = Person::GetPerson($name);
$myPerson->AddFeedback('مقالة رائعة!', 'SomeReader', date('Ym-d'));
?>
لاحظ أنه لا يوجد بيان تبديل هنا، والأهم من ذلك، هناك نقص في المعلومات حول نوع الكائن Person::GetPerson() الذي سيرجعه. والشخص الآخر::AddFeedback() هو أسلوب متعدد الأشكال. يتم تغليف السلوك بالكامل من خلال فئات محددة. تذكر، سواء كنا نستخدم David أو Charles أو Alejandro هنا، فإن رمز الاتصال لا يجب أن يعرف أبدًا ما تفعله الفئة المحددة، فقط الفئة الأساسية.
على الرغم من أن مثالي ليس مثاليًا، إلا أنه يوضح الاستخدام الأساسي لتعدد الأشكال من منظور رمز الاتصال. الآن نحن بحاجة إلى تحليل التنفيذ الداخلي لهذه الفئات. أحد الأشياء الرائعة في الاشتقاق من فئة أساسية هو أن الفئة المشتقة يمكنها الوصول إلى سلوك الفئة الأصلية. غالبًا ما يكون هذا هو التنفيذ الافتراضي، ولكنه قد يحدث أيضًا في سلاسل وراثة الفئة لإنشاء سلوك أكثر تعقيدًا. وفيما يلي عرض بسيط لهذا الوضع.
<?php
شخص الصف{
الدالة AddFeedback($comment, $sender, $date){
// إضافة تعليقات إلى قاعدة البيانات}
}
فئة ديفيد يمتد الشخص {
وظيفة AddFeedback(تعليق $, $sender){
الأصل::AddFeedback($comment, $sender,
التاريخ('يم-د'));
}
}
>
هنا، يتم استدعاء أسلوب Person::AddFeedback أولاً عند تنفيذ أسلوب AddFeedback في فئة David. قد تلاحظ أنه يحاكي طريقة التحميل الزائد في C++ أو Java أو C#. ضع في اعتبارك أن هذا مجرد مثال مبسط وأن الكود الفعلي الذي تكتبه يعتمد بشكل كامل على مشروعك الفعلي.
4. الربط المتأخر في PHP 5
في رأيي، يعد الربط المتأخر سببًا مهمًا وراء كون Java وC# مقنعين للغاية. إنها تسمح لطرق الفئة الأساسية باستدعاء الأساليب باستخدام "هذا" أو $this (حتى لو لم تكن موجودة في الفئة الأساسية أو قد يتم استبدال استدعاء طريقة في الفئة الأساسية بإصدار آخر في الفئة الموروثة). يمكنك اعتبار التطبيقات التالية مسموحًا بها في PHP:
<?php
شخص الصف{
الدالة AddFeedback($messageArray) {
$this->ParseFeedback($messageArray);
// الكتابة إلى قاعدة البيانات}
}
فئة ديفيد يمتد الشخص {
الدالة ParseFeedback($messageArray){
// قم ببعض التحليلات}
}
>
تذكر أنه لا يوجد ParseFeedback في فئة الشخص. الآن، بافتراض أن لديك هذا الجزء من كود التنفيذ (في هذا المثال)، سيؤدي هذا إلى أن يكون $myPerson كائن David:
<?php
$myPerson = Person::GetPerson($name);
$myPerson->AddFeedback($messageArray);
>
حدث خطأ في التحليل! رسالة الخطأ العامة هي أن طريقة ParseFeedback غير موجودة أو بعض المعلومات المشابهة. دعونا نتحدث عن الربط المتأخر في PHP 5! بعد ذلك، دعونا نلخص مفهوم الربط المتأخر.
الربط المتأخر يعني أن استدعاء الأسلوب غير مرتبط بالكائن الهدف حتى اللحظة الأخيرة. هذا يعني أنه عند استدعاء الطريقة في وقت التشغيل، يكون لهذه الكائنات بالفعل نوع محدد. في المثال أعلاه، قمت باستدعاء David::AddFeedback()، وبما أن $this في David::AddFeedback() يشير إلى كائن David، فيمكنك افتراض منطقيًا أن طريقة ParseFeedback() موجودة - ولكنها في الواقع غير موجودة موجود لأن AddFeedback() محدد في الشخص ويتم استدعاء ParseFeedback() من فئة الشخص.
لسوء الحظ، لا توجد طريقة سهلة للتخلص من هذا السلوك في PHP 5. هذا يعني أنك قد تكون عاجزًا بعض الشيء عندما تريد إنشاء تسلسل هرمي مرن متعدد الأشكال للفئة.
يجب أن أشير إلى أنني اخترت PHP 5 كلغة تعبير لهذه المقالة ببساطة لأن: هذه اللغة لا تدرك التجريد المثالي لمفهوم الكائن! وهذا أمر مفهوم لأن PHP 5 لا يزال في نسخته التجريبية. بالإضافة إلى ذلك، بعد إضافة الفئات والواجهات المجردة إلى اللغة، يجب أيضًا تنفيذ الربط المتأخر.
5. ملخص
في هذه المرحلة، يجب أن يكون لديك فهم أساسي لماهية تعدد الأشكال ولماذا PHP 5 ليس مثاليًا في تحقيق تعدد الأشكال. بشكل عام، يجب أن تعرف كيفية استخدام نموذج كائن متعدد الأشكال لتغليف السلوك الشرطي. بالطبع، يؤدي هذا إلى زيادة مرونة كائناتك ويعني قدرًا أقل من التعليمات البرمجية التي يجب تنفيذها. بالإضافة إلى ذلك، يمكنك زيادة وضوح التعليمات البرمجية الخاصة بك عن طريق تغليف السلوك الذي يلبي شروطًا معينة (اعتمادًا على حالة الكائن).