30-09-12, 06:36 AM
إذا أردت إنشاء فئة جديدة بالاسم Employee فهنا ستجد أن كل موظف ما هو إلا شخص عادي لديه الخصائص والوظائف السابق ذكرها ( FirstName , LastName , Age , Address , EMail ) وكذلك DialPhone و SendMail. وهنا إذا لم تكن تعرف للوراثة معنى فستقوم بإنشاء تلك الخصائص أو المتغيرات والوظائف ثانية من جديد ، وستضيف عليها طبعا بعض الخصائص التي تخص الموظف مثل ( Salary , WorkHours , WorkAddress , WorkPhone , EmployeeID , OfficeNumber ) ، وتريد كذلك استخدام الوظيفة DialPhone ولكن بشكل آخر وبأسلوب أخر.
وكذلك ستظل المشكلة قائمة إذا أردت عمل فئة جديدة بالاسم Manager ، فستحتاج كافة الخصائص والوظائف الموجودة في كلتا الفئتين Person وكذلك Employee وستضيف عليها لاحقاً بعض الخصائص والأحداث والوظائف وذلك لان كل مدير ما هو إلا موظف وما كل موظف إلا شخص عادي.
![[صورة مرفقة: 59_01348971001.jpg]](https://vb4arb.com/vb/uploaded/59_01348971001.jpg)
الشكل السابق كان مثالاً لمشكلتنا السابق تفصيلها. من مميزات الوراثة والتوريث الأساسية هي إعادة استخدام الكود مرة أخرى دون إنشاؤه أو حتى إعادة كتابته مرة أخرى. ومعنى هذا أنك مثلا عندما ستكون بصدد إنشاء الفئة المسماة Employee ستقوم بإنشاء ( FirstName , LastName , Age , Address , EMail ) وكذلك الوظائف والطرق السابق ذكرها. ولكن بمجرد أخذك قرار الوراثة من الفئة الأب Person ستُحَل هذه المشكلة بالكامل.
التوريث المتدرج Inheritance Hierarchies
إعادة استخدام الكود في التوريث لا يحميك من الخطأ في إعادة كتابة الكود فحسب ولكن كذلك يجعل تطوير الفئة أو التطبيق بصفة عامة اسهل من ذي قبل. بفرض مثلاً أنك تقوم بتطوير مجموعة من الفئات كما في الشكل السابق ، وبعد انتهائك من الفئات Person كفئة أساسية ParentClass ، وكذلك الفئات المشتقة مثل Employee و Manager و Customer و Secretary كفئات مشتقة Subclasses ... أردت أن تضيف الخاصية BirthDate ، فلو ابتعدت عن مبادئ التوريث التي جاءت بها البرمجة الموجهة للكائنات فستقوم بإضافة هذه الخاصية إلى كل الفئات السابق ذكرها ، أما مع OOP ومع Inheritance فما عليك إلا أن تضيف هذه الخاصية في الفئة Person لأنها الفئة الأب ومن ثم للفئات الأخرى يورثوا خواص الفئة الأب وانتهى الموضوع وتم حل المشكلة.
كمثال آخر ، بفرض أنك تريد تعديل أو حذف أحد الخصائص أو الوسائل ولتكن مثلاً داخل خاصية FirstName ، فما عليك إلا أن تقوم بتعديل الخاصية المذكورة في الفئة الأب وهي Person ولا عليك أن تقوم بالتعديل في كل الفئات التي تحمل نفس الخاصية.
** معلومة **
تدعم بعض اللغات التوريث المتعدد ، بمعنى أنه يمكنك في فئة مشتقة من أكثر من فئة أب. فلنفترض أن هناك فئة بالاسم Car وتحتوي على بعض الخصائص والوسائل والأحداث الخاصة بهذه الفئة ، وهناك فئة أخرى بالاسم House ولهذه الفئة أيضا ما يميزها من الخصائص والأحداث. ولو استخدمنا التوريث المتعدد MultipleInheritance فسنحصل على فئة أخرى ولتكن بالاسم MotorHome ويحمل مميزات كلتا الفئتين Car و House.
أنا شخصياً – بعقلي الضيق الفكر - غير متخيل الفئة الناتجة لأن الفئات الأساسية غير متجانسة ، ولكن Microsoft أشفقت عليّ وجعلت VisualBasic.NET لا يدعم التوريث المتعدد وجعلت الفئة لا تورث من أخرى إلا مرة واحدة فقط. إذا احتجت لاستخدام التوريث المتعدد فعليك أن تستخدم الواجهات Interfaces ، فبدلا من تعريف أكثر من ParentClass فقم بتعريف أو التصريح عن أكثر من ParentInterface وعندها يمكنك إنشاء فئة مشتقة تنفذ أو تطبق داخلها أكثر من واجهة Interface كما يحلو لك. وللعلم لا تورث الفئة أية أكواد من الواجهات ولكن من اسمها ستأخذ فقط واجهة وتضيفها على الفئة.
التوريث وإعادة القيادة Overriding
إذا قمنا باشتقاق الفئة Employee من الفئة Person ، فسنقوم بإضافة خواص ووسائل جديدة للفئة Employee كما تم الذكر في أول الموضوع ، ولكن من ضمن المشاكل التي واجهتنا هي أن الوظيفة DialPhone تقوم بالاتصال بالشخص عن طريق المودم ولكن تتصل بتليفون المنزل ، أما في الفئة Employee نحتاج نفس الوظيفة وبنفس إمكانياتها باستثناء رقم التليفون ، فنحن نريد استبداله بتليفون العمل. لو بعدنا قليلاً عن OOP وكذلك الـ Overriding فسنقول أن الحل هي إنشاء الوظيفة من جديد ، ولكن مع OOP فسنستخدم إحدى مميزاتها الفرعية وهي إعادة القيادة للوظائف والوسائل ، ولكن من شروط استخدام إعادة القيادة هي أن يكون الإجراء الأساسي في الفئة الأب معرف أو مصرح على أنه قابل لإعادة القيادة من مكان آخر. فيجب أن يكون الإجراء في الفئة الأب معرف كما يلي :
وعند الإشتقاق أو التوريث وإقرار تولي القيادة من الفئة المشتقة فسيكون الإجراء معرف أو مصرح عنه كما يلي :
تتيح لك إعادة القيادة استخدام إجراء بنفس الاسم مرة أخرى ولكن تحت أكواد جديدة ووظائف من الممكن أن تكون مغايرة تماما للوظيفة الموجودة في الفئة الأب ولكن بشرط أن تكون الوظيفة معرفة في الفئة الأب على النحو التالي Public Overridable Sub ويقصد بها أي ان هذا الاجراء قابل لإعادة تولي القيادة من مكان آخر ، ولتولي القيادة من مكان آخر فيجب التصريح عن الوظيفة في الفئة المشتقة كما يلي Public Overrides Sub ، وبهذا تكون قد أخفيت هذه الوظيفة في الفئة الأب وأظهرتها من جديد في الفئة المشتقة وبشكل جديد وذلك كما رأينا في مثالنا السابق.
** ملحوظة **
كي تعطي أمر بالوراثة من فئة أب فما عليك إلا كتابة ما يلي :
حيث Person هي الفئة الأب المشتق منها خصائصها داخل الفئة المشتقة ولتكن كما ذكرنا الفئة Employee ... يمكنك النظر في المشروع التالي لرؤية الأكواد المتعلقة بالوراثة وكذلك إعادة القيادة ، ولكن عند تحميلك للمثال ستجد به فئة بالاسم Person وفئة أخرى بالاسم Employee ونموذج بالاسم Form1 ، قم بتعريف كائنات جديدة كنسخة من الفئات السابق ذكرها وشاهد مميزات إعادة القيادة وكذلك مميزات الوراثة بنفسك.
بما أننا قد ذكرنا إعادة القيادة Overriding فتعال نذكر شكل آخر من إعادة القيادة وهو Shadow.
إعادة القيادة والظل Shadows
تحت العنوان الجانبي السابق (التوريث وإعادة القيادةOverriding ) قمنا بطرح مشكلة وهي إعادة كتابة إجراء بنفس الاسم لكن مع اختلاف الوظيفة التي خُلِق من أجلها. هنا تظهر مشكلة جديدة : ماذا لو أننا لدينا الفئة Person بما فيها للإجراء DialPhone ولكنه غير قابل لإعادة القيادة من مكان آخر ، وكذلك الفئة Person تم تغليفها وجلبها للمشروع في صورة DLL File وعندئذ لا يمكن التعديل فيما ورد بها وكذلك الإجراء المسمى DialPhone في الفئة الأب غير قابل لإعادة تولي القيادة يعني أنه لم يصرح عنه كـ Overridable Sub وبالتالي لا يمكننا إعادة تولي قيادته طبقاً لم تم شرحه في العنوان الفرعي السابق ( التوريث وإعادة القيادة ) ، ولكننا في نفس الوقت نريد إعادة تولي القيادة للإجراء DialPhone وتغيير بعض خصائصه وعدم إظهار نفس الإجراء في الفئة الأب ... ماذا سنفعل ؟؟؟. باستخدام للكلمة المفتاحية Shadows أثناء تصريحك عن الإجراء في الفئة المشتقة بهذا تكون قد فعلت أو قمت بما تقوم به Overridable Sub دون أن يكون الإجراء قابل لإعادة تولي القيادة من مكان آخر ، فكلمة Shadows تخفي الإجراء في الفئة الأب وتُظهر فقط الإجراء بنفس الاسم في الفئة المشتقة.
** ملحوظة مهمة **
بفرض أن هناك في الفئة الأب متغير نصي بالاسم ( FirstName ) ، وفي الفئة المشتقة يوجد إجراء فرعي بالاسم ( FirstName ) .. هنا لا تستخدم shadows لان هذا سيسبب تعارض لان أنواع الكائنات غير متجانسة فهذا متغير وهذه Method.
--------
هنا ينتهي الجزء الاول من الدرس
--------
وشكر خاص للاستاذ احمد نجم
وكذلك ستظل المشكلة قائمة إذا أردت عمل فئة جديدة بالاسم Manager ، فستحتاج كافة الخصائص والوظائف الموجودة في كلتا الفئتين Person وكذلك Employee وستضيف عليها لاحقاً بعض الخصائص والأحداث والوظائف وذلك لان كل مدير ما هو إلا موظف وما كل موظف إلا شخص عادي.
![[صورة مرفقة: 59_01348971001.jpg]](https://vb4arb.com/vb/uploaded/59_01348971001.jpg)
الشكل السابق كان مثالاً لمشكلتنا السابق تفصيلها. من مميزات الوراثة والتوريث الأساسية هي إعادة استخدام الكود مرة أخرى دون إنشاؤه أو حتى إعادة كتابته مرة أخرى. ومعنى هذا أنك مثلا عندما ستكون بصدد إنشاء الفئة المسماة Employee ستقوم بإنشاء ( FirstName , LastName , Age , Address , EMail ) وكذلك الوظائف والطرق السابق ذكرها. ولكن بمجرد أخذك قرار الوراثة من الفئة الأب Person ستُحَل هذه المشكلة بالكامل.
التوريث المتدرج Inheritance Hierarchies
إعادة استخدام الكود في التوريث لا يحميك من الخطأ في إعادة كتابة الكود فحسب ولكن كذلك يجعل تطوير الفئة أو التطبيق بصفة عامة اسهل من ذي قبل. بفرض مثلاً أنك تقوم بتطوير مجموعة من الفئات كما في الشكل السابق ، وبعد انتهائك من الفئات Person كفئة أساسية ParentClass ، وكذلك الفئات المشتقة مثل Employee و Manager و Customer و Secretary كفئات مشتقة Subclasses ... أردت أن تضيف الخاصية BirthDate ، فلو ابتعدت عن مبادئ التوريث التي جاءت بها البرمجة الموجهة للكائنات فستقوم بإضافة هذه الخاصية إلى كل الفئات السابق ذكرها ، أما مع OOP ومع Inheritance فما عليك إلا أن تضيف هذه الخاصية في الفئة Person لأنها الفئة الأب ومن ثم للفئات الأخرى يورثوا خواص الفئة الأب وانتهى الموضوع وتم حل المشكلة.
كمثال آخر ، بفرض أنك تريد تعديل أو حذف أحد الخصائص أو الوسائل ولتكن مثلاً داخل خاصية FirstName ، فما عليك إلا أن تقوم بتعديل الخاصية المذكورة في الفئة الأب وهي Person ولا عليك أن تقوم بالتعديل في كل الفئات التي تحمل نفس الخاصية.
** معلومة **
تدعم بعض اللغات التوريث المتعدد ، بمعنى أنه يمكنك في فئة مشتقة من أكثر من فئة أب. فلنفترض أن هناك فئة بالاسم Car وتحتوي على بعض الخصائص والوسائل والأحداث الخاصة بهذه الفئة ، وهناك فئة أخرى بالاسم House ولهذه الفئة أيضا ما يميزها من الخصائص والأحداث. ولو استخدمنا التوريث المتعدد MultipleInheritance فسنحصل على فئة أخرى ولتكن بالاسم MotorHome ويحمل مميزات كلتا الفئتين Car و House.
أنا شخصياً – بعقلي الضيق الفكر - غير متخيل الفئة الناتجة لأن الفئات الأساسية غير متجانسة ، ولكن Microsoft أشفقت عليّ وجعلت VisualBasic.NET لا يدعم التوريث المتعدد وجعلت الفئة لا تورث من أخرى إلا مرة واحدة فقط. إذا احتجت لاستخدام التوريث المتعدد فعليك أن تستخدم الواجهات Interfaces ، فبدلا من تعريف أكثر من ParentClass فقم بتعريف أو التصريح عن أكثر من ParentInterface وعندها يمكنك إنشاء فئة مشتقة تنفذ أو تطبق داخلها أكثر من واجهة Interface كما يحلو لك. وللعلم لا تورث الفئة أية أكواد من الواجهات ولكن من اسمها ستأخذ فقط واجهة وتضيفها على الفئة.
التوريث وإعادة القيادة Overriding
إذا قمنا باشتقاق الفئة Employee من الفئة Person ، فسنقوم بإضافة خواص ووسائل جديدة للفئة Employee كما تم الذكر في أول الموضوع ، ولكن من ضمن المشاكل التي واجهتنا هي أن الوظيفة DialPhone تقوم بالاتصال بالشخص عن طريق المودم ولكن تتصل بتليفون المنزل ، أما في الفئة Employee نحتاج نفس الوظيفة وبنفس إمكانياتها باستثناء رقم التليفون ، فنحن نريد استبداله بتليفون العمل. لو بعدنا قليلاً عن OOP وكذلك الـ Overriding فسنقول أن الحل هي إنشاء الوظيفة من جديد ، ولكن مع OOP فسنستخدم إحدى مميزاتها الفرعية وهي إعادة القيادة للوظائف والوسائل ، ولكن من شروط استخدام إعادة القيادة هي أن يكون الإجراء الأساسي في الفئة الأب معرف أو مصرح على أنه قابل لإعادة القيادة من مكان آخر. فيجب أن يكون الإجراء في الفئة الأب معرف كما يلي :
كود :
[b][SIZE=4][color=#008000]'Dial the phone using (Phone) property.[/color][/SIZE][/b][b][SIZE=4]
[/SIZE][/b][b][b][SIZE=4][color=#0000FF]Public Overridable Sub [/color]DialPhone()[/SIZE][/b]
[SIZE=4][b][SIZE=4]MsgBox([color=#B22222]"Dial : "[/color] & [color=#0000FF]Me[/color].Phone)[/SIZE][/b]
[b][SIZE=4]'Other Code[/SIZE][/b]
[color=#0000FF][b][SIZE=4]End Sub[/SIZE][/b][/color][/SIZE][/b]وعند الإشتقاق أو التوريث وإقرار تولي القيادة من الفئة المشتقة فسيكون الإجراء معرف أو مصرح عنه كما يلي :
كود :
[b][SIZE=4][color=#008000]'Dial the phone using (WorkPhone) property.[/color][/SIZE][/b][b][SIZE=4]
[/SIZE][/b][b][b][SIZE=4][color=#0000FF]Public Overrides Sub[/color] DialPhone()[/SIZE][/b]
[SIZE=4][b][SIZE=4]MsgBox([color=#B22222]"Dial : "[/color] & [color=#0000FF]Me[/color].WorkPhone)[/SIZE][/b]
[color=#008000][b][SIZE=4]'Other Code[/SIZE][/b][/color]
[color=#0000FF][b][SIZE=4]End Sub[/SIZE][/b][/color][/SIZE][/b]تتيح لك إعادة القيادة استخدام إجراء بنفس الاسم مرة أخرى ولكن تحت أكواد جديدة ووظائف من الممكن أن تكون مغايرة تماما للوظيفة الموجودة في الفئة الأب ولكن بشرط أن تكون الوظيفة معرفة في الفئة الأب على النحو التالي Public Overridable Sub ويقصد بها أي ان هذا الاجراء قابل لإعادة تولي القيادة من مكان آخر ، ولتولي القيادة من مكان آخر فيجب التصريح عن الوظيفة في الفئة المشتقة كما يلي Public Overrides Sub ، وبهذا تكون قد أخفيت هذه الوظيفة في الفئة الأب وأظهرتها من جديد في الفئة المشتقة وبشكل جديد وذلك كما رأينا في مثالنا السابق.
** ملحوظة **
كي تعطي أمر بالوراثة من فئة أب فما عليك إلا كتابة ما يلي :
كود :
[b][SIZE=4][color=#0000FF]Inherits [/color]Person[/SIZE][/b]حيث Person هي الفئة الأب المشتق منها خصائصها داخل الفئة المشتقة ولتكن كما ذكرنا الفئة Employee ... يمكنك النظر في المشروع التالي لرؤية الأكواد المتعلقة بالوراثة وكذلك إعادة القيادة ، ولكن عند تحميلك للمثال ستجد به فئة بالاسم Person وفئة أخرى بالاسم Employee ونموذج بالاسم Form1 ، قم بتعريف كائنات جديدة كنسخة من الفئات السابق ذكرها وشاهد مميزات إعادة القيادة وكذلك مميزات الوراثة بنفسك.
بما أننا قد ذكرنا إعادة القيادة Overriding فتعال نذكر شكل آخر من إعادة القيادة وهو Shadow.
إعادة القيادة والظل Shadows
تحت العنوان الجانبي السابق (التوريث وإعادة القيادةOverriding ) قمنا بطرح مشكلة وهي إعادة كتابة إجراء بنفس الاسم لكن مع اختلاف الوظيفة التي خُلِق من أجلها. هنا تظهر مشكلة جديدة : ماذا لو أننا لدينا الفئة Person بما فيها للإجراء DialPhone ولكنه غير قابل لإعادة القيادة من مكان آخر ، وكذلك الفئة Person تم تغليفها وجلبها للمشروع في صورة DLL File وعندئذ لا يمكن التعديل فيما ورد بها وكذلك الإجراء المسمى DialPhone في الفئة الأب غير قابل لإعادة تولي القيادة يعني أنه لم يصرح عنه كـ Overridable Sub وبالتالي لا يمكننا إعادة تولي قيادته طبقاً لم تم شرحه في العنوان الفرعي السابق ( التوريث وإعادة القيادة ) ، ولكننا في نفس الوقت نريد إعادة تولي القيادة للإجراء DialPhone وتغيير بعض خصائصه وعدم إظهار نفس الإجراء في الفئة الأب ... ماذا سنفعل ؟؟؟. باستخدام للكلمة المفتاحية Shadows أثناء تصريحك عن الإجراء في الفئة المشتقة بهذا تكون قد فعلت أو قمت بما تقوم به Overridable Sub دون أن يكون الإجراء قابل لإعادة تولي القيادة من مكان آخر ، فكلمة Shadows تخفي الإجراء في الفئة الأب وتُظهر فقط الإجراء بنفس الاسم في الفئة المشتقة.
** ملحوظة مهمة **
بفرض أن هناك في الفئة الأب متغير نصي بالاسم ( FirstName ) ، وفي الفئة المشتقة يوجد إجراء فرعي بالاسم ( FirstName ) .. هنا لا تستخدم shadows لان هذا سيسبب تعارض لان أنواع الكائنات غير متجانسة فهذا متغير وهذه Method.
--------
هنا ينتهي الجزء الاول من الدرس
--------
وشكر خاص للاستاذ احمد نجم
<---------------------------------------------------------------->
![[صورة مرفقة: 67og849couh458t6g.jpg]](https://www.mediafire.com/convkey/e179/67og849couh458t6g.jpg)

