الفرق بين المراجعتين لصفحة: «Python/inhertance»
لا ملخص تعديل |
طلا ملخص تعديل |
||
سطر 17: | سطر 17: | ||
أما تحليل الإشارات إلى التوابع فيجري بالصورة التالية: تبحث اللغة عن خاصية الصنف المقابلة نزولًا إلى سلسلة الأصناف الأساسية إن اقتضت الحاجة، وتكون الإشارة إلى التابع صالحة إن نتج عن عملية البحث هذه كائن دالة (function object). | أما تحليل الإشارات إلى التوابع فيجري بالصورة التالية: تبحث اللغة عن خاصية الصنف المقابلة نزولًا إلى سلسلة الأصناف الأساسية إن اقتضت الحاجة، وتكون الإشارة إلى التابع صالحة إن نتج عن عملية البحث هذه كائن دالة (function object). | ||
يمكن للأصناف المشتقة أن تعيد تعريف توابع الأصناف الأساسية، ولما كانت التوابع لا تمتلك أي امتيازات خاصة عند استدعاء توابع أخرى في الكائن نفسه، فقد يؤدي استدعاء تابع في الصنف الأساسي وظيفته استدعاء تابع آخر في نفس الكائن، إلى استدعاء تابع في الصنف المشتق (يعيد تعريف التابع الأساسي). (إن كنت خبيرًا في لغة C++ فإنّ جميع التوابع في بايثون هي <code>virtual</code>). | يمكن للأصناف المشتقة أن تعيد تعريف توابع الأصناف الأساسية، ولما كانت التوابع لا تمتلك أي امتيازات خاصة عند استدعاء توابع أخرى في الكائن نفسه، فقد يؤدي استدعاء تابع في الصنف الأساسي وظيفته استدعاء تابع آخر في نفس الكائن، إلى استدعاء تابع في الصنف المشتق (يعيد تعريف التابع الأساسي). (إن كنت خبيرًا في لغة C++ فإنّ جميع التوابع في بايثون هي ظاهرية <code>virtual</code>). | ||
تميل التوابع المشتقة إلى إعادة تعريف التوابع الأساسية بدلًا من استبدال التابع الأساسي الذي يحمل الاسم نفسه. | تميل التوابع المشتقة إلى إعادة تعريف التوابع الأساسية بدلًا من استبدال التابع الأساسي الذي يحمل الاسم نفسه. | ||
سطر 26: | سطر 26: | ||
تقدّم بايثون دالتين داخليتين (built-in) يمكن الاستفادة منهما في موضوع الوراثة: | تقدّم بايثون دالتين داخليتين (built-in) يمكن الاستفادة منهما في موضوع الوراثة: | ||
* تستخدم الدالة <code>isinstance()</code> للتحقّق من نوع النسخة: لا يعطي التعبير <code>isinstance(obj, int)</code> النتيجة <code>True</code> إلا إذا كان <code>obj.__class__</code> من نوع <code>[[Python/int|int]]</code> أو أي صنف مشتقّ من هذا النوع. | |||
* تستخدم الدالة <code>issubclass()</code> للتحقق من وراثة الصنف: يعطي التعبير <code>issubclass(bool, int)</code> النتيجة <code>True</code> لأنّ النوع <code>[[Python/boolean|bool]]</code> هو صنف فرعي من النوع <code>[[Python/int|int]]</code> . أما التعبير <code>issubclass(float, int)</code> فيعطي النتيجة <code>False</code> لأنّ <code>[[Python/float|float]]</code> ليس صنفًا فرعيًا من <code>[[Python/int|int]]</code>. | |||
== الوراثة المتعددة == | |||
== الوراثة | |||
تدعم بايثون كذلك شكلًا من أشكال الوراثة المتعددة، إذ يمكن تعريف صنف مع استخدام عدد من الأصناف الأساسية وكما موضح في المثال التالي:<syntaxhighlight lang="python3"> | تدعم بايثون كذلك شكلًا من أشكال الوراثة المتعددة، إذ يمكن تعريف صنف مع استخدام عدد من الأصناف الأساسية وكما موضح في المثال التالي:<syntaxhighlight lang="python3"> | ||
class DerivedClassName(Base1, Base2, Base3): | class DerivedClassName(Base1, Base2, Base3): | ||
سطر 48: | سطر 46: | ||
== مصادر == | == مصادر == | ||
صفحة [https://docs.python.org/3/tutorial/classes.html#inheritance Classes] في توثيق بايثون الرسمي. | * صفحة [https://docs.python.org/3/tutorial/classes.html#inheritance Classes] في توثيق بايثون الرسمي. | ||
[[تصنيف:Python]] | [[تصنيف:Python]] | ||
[[تصنيف:Python Classes]] | [[تصنيف:Python Classes]] |
مراجعة 11:07، 17 مارس 2018
تدعم بايثون شأنها في ذلك شأن أي لغة برمجية كائنية التوجه مفهوم الوراثة، وأبسط صيغة لتعريف صنف مشتق أو موروث من صنف آخر هي:
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
يجب أن يكون الاسم BaseClassName
معرّفًا في النطاق الذي يحتوي تعريف الصنف المشتق. ويمكن استخدام أي تعبير محلّ اسم الصنف الأساسي، ويمكن لهذا أن يكون مفيدًا عندما يكون الصنف الأساسي معرّفًا في وحدة أخرى على سبيل المثال:
class DerivedClassName(modname.BaseClassName):
يجري تنفيذ تعريف الصنف المشتق بنفس الطريقة المتبعة في الصنف الأساسي، وعند إنشاء كائن الصنف تتذكّر اللغة الصنف الأساسي. تستخدم هذه الميزة لتحليل الإشارات إلى الخاصيات، فعندما تكون الخاصية المطلوبة غير موجودة في الصنف، تنتقل اللغة للبحث عنها في الصنف الأساسي، وتنطبق هذه القاعدة مرة أخرى إن كان الصنف الأساسي مشتقًا من صنف آخر. لا توجد صيغة خاصة لتمثيل الأصناف المشتقة، بل تستخدم الصيغة الاعتيادية:
DerivedClassName()
تنشئ العبارة السابقة نسخة جديدة من الصنف.
أما تحليل الإشارات إلى التوابع فيجري بالصورة التالية: تبحث اللغة عن خاصية الصنف المقابلة نزولًا إلى سلسلة الأصناف الأساسية إن اقتضت الحاجة، وتكون الإشارة إلى التابع صالحة إن نتج عن عملية البحث هذه كائن دالة (function object).
يمكن للأصناف المشتقة أن تعيد تعريف توابع الأصناف الأساسية، ولما كانت التوابع لا تمتلك أي امتيازات خاصة عند استدعاء توابع أخرى في الكائن نفسه، فقد يؤدي استدعاء تابع في الصنف الأساسي وظيفته استدعاء تابع آخر في نفس الكائن، إلى استدعاء تابع في الصنف المشتق (يعيد تعريف التابع الأساسي). (إن كنت خبيرًا في لغة C++ فإنّ جميع التوابع في بايثون هي ظاهرية virtual
).
تميل التوابع المشتقة إلى إعادة تعريف التوابع الأساسية بدلًا من استبدال التابع الأساسي الذي يحمل الاسم نفسه.
يمكن استدعاء التابع الأساسي بصورة مباشرة عن طريق عبارة الاستدعاء:
BaseClassName.methodname(self, arguments)
قد تكون هذه الطريقة مفيدة عند استخدام الشيفرة من قبل أشخاص آخرين. (لاحظ أنّ عبارة الاستدعاء هذه صالحة فقط عندما يكون بالإمكان الوصول إلى الصنف الأساسي باستخدام الاسم BaseClassName
ضمن النطاق العام).
تقدّم بايثون دالتين داخليتين (built-in) يمكن الاستفادة منهما في موضوع الوراثة:
- تستخدم الدالة
isinstance()
للتحقّق من نوع النسخة: لا يعطي التعبيرisinstance(obj, int)
النتيجةTrue
إلا إذا كانobj.__class__
من نوعint
أو أي صنف مشتقّ من هذا النوع. - تستخدم الدالة
issubclass()
للتحقق من وراثة الصنف: يعطي التعبيرissubclass(bool, int)
النتيجةTrue
لأنّ النوعbool
هو صنف فرعي من النوعint
. أما التعبيرissubclass(float, int)
فيعطي النتيجةFalse
لأنّfloat
ليس صنفًا فرعيًا منint
.
الوراثة المتعددة
تدعم بايثون كذلك شكلًا من أشكال الوراثة المتعددة، إذ يمكن تعريف صنف مع استخدام عدد من الأصناف الأساسية وكما موضح في المثال التالي:
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
في معظم الحالات يمكن القول أن عملية البحث عن الخاصيات الموروثة من الصنف الأب تجري حسب بُعْدِ الصنف الأب عن الصنف الابن، ومن اليسار إلى اليمين، ولا يجري البحث مرتين في الصنف الواحد إذا كان هناك إعادة تعريف ضمن التسلسل الهرمي للأصناف المورَِّثة. وهذا يعني أنّه إن لم تفلح اللغة في العثور على الخاصية في الصنف المشتق DerivedClassName
فستبحث عنها في الصنف الأساسي Base1
، وإن لم تعثر عليها هناك فستبحث عنها في الصنف الأساسي Base2
وهكذا دواليك.
الأمر أكثر تعقيدًا ممّا سبق في الواقع، فترتيب عملية تحليل التوابع يتغيّر بصورة ديناميكية لغرض دعم الاستدعاءات المشتركة للتابع super()
. هذا الأسلوب معروف في بعض لغات البرمجة التي تدعم الوراثة المتعددة باسم استدعاء التابع اللاحق (call-next-method) وهو أكثر قوّة من استدعاء التوابع في الأصناف الأساسية (super call) في اللغات التي تدعم الوراثة المفردة.
عملية الترتيب الديناميكة ضرورية لأنّ جميع حالات الوراثة المتعددة تظهر علاقة واحدة أو أكثر على شكل ماسة (أي يمكن الوصول إلى أحد الأصناف الآباء على الأقل عن طريق مسارات متعددة تبدأ من الصنف الأدنى في شجرة الوراثة وتنتهي كلها بالصنف الأب).
فعلى سبيل المثال، ترث جميع الأصناف من الكائن؛ لذا فإنّ أي حالة من الوراثة المتعددة ستقدّم أكثر من طريق للوصول إلى ذلك الكائن. ولتجنب الوصول إلى الأصناف الأساسية أكثر من مرة واحدة تعمل خوارزمية البحث الديناميكية على جعل ترتيب عملية البحث خطّيًا linear بصورة تحافظ على طريقة الترتيب من اليسار إلى اليمين والمحدّدة في كل صنف، وتستدعي كل صنف أب مرّة واحدة فقط، وعلى وتيرة واحدة (بمعنى أنّه يمكن تفريع الصنف دون التأثير على ترتيب الأصناف الآباء).
مصادر
- صفحة Classes في توثيق بايثون الرسمي.