اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'التعددية الشكلية'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 1 نتيجة

  1. تحدثنا في الدرسين السابقين عن المبادئ الأوليّة لتطبيق مفاهيم البرمجة الكائنيّة التوجّه في سي شارب. سننهي في هذا الدرس تطبيق هذه المبادئ، حيث سنتناول موضوع الوراثة Inheritance والتعدديّة الشكليّة Polymorphism، كما سنتعرّف على محدّد الوصول protected الذي يُستخدم في الوراثة. الوراثة Inheritance سبق وأن قدّمنا للوراثة، واتفقنا على أنّها من أهمّ المفاهيم التي يمكن أن تدعمها لغات البرمجة كائنيّة التوجّه. في الحقيقة يرث أيّ صنف موجود في إطار عمل دوت نت أو أيّ صنف تنشئه بنفسك بشكل مباشر أو غير مباشر من الصنف Object حتى ولو لم نخبر مترجم سي شارب بذلك، حيث سيعمل المترجم على الوراثة منه بشكل ضمنيّ. هذا الصنف ذو دلالة عامّة، وهو غير مفيد كثيرًا كاستخدام بحدّ ذاته. يحتوي الصنف Object على عدد قليل من التوابع كأعضاء ضمنه مثل Equals و GetHashCode و GetType و ToString. التابع الأكثر استخدامًا هو التابع ToString، وهو يُستخدَم عادةً للحصول على التمثيل النصيّ لأيّ كائن. لكي نفهم الوراثة بشكل عمليّ لا بدّ لنا من مثال تمهيديّ. سننشئ لهذا الغرض صنف أب سأسمّيه Father. سيكون هذا الصنف هو الأساس الذي نرث منه. لهذا الصنف الشكل التالي: class Father { public Father() { Console.WriteLine("Father: In Constructor"); } public void MyMethod() { Console.WriteLine("Father: In MyMethod"); } } يحتوي هذا الصنف على التابع MyMethod الذي يحوي الكلمة void قبل اسم التابع مباشرةً. تعني هذه الكلمة أنّ التابع MyMethod لن يُرجع أي قيمة للشيفرة التي استدعته. كما يحتوي الصنف Father على البانية عديمة الوسائط Father. وضعت عبارتي Writeline في كلّ تابع من باب التوضيح. الآن سنعرّف صنفًا جديدًا لنسمّه Child يرث من الصنف Father على الشكل التالي: class Child : Father { } قد يبدو الصنف Child فارغًا إلّا أنّه ليس كذلك. لاحظ من السطر الأوّل لتصريح هذا الصنف كيف وضعنا النقطتان الرأسيّتان (:) ومن ثمّ اسم الصنف Father. يخبر ذلك مترجم سي شارب أنّنا نريد من الصنف Child أن يرث من الصنف Father. في الحقيقة جميع الأعضاء المعرّفة ضمن الصنف Father ستصبح موجودة تلقائيًّا ضمن الصنف Child، بل ويمكن إضافة المزيد من الأعضاء إلى الصنف Child بحسب الحاجة. أنشئ مشروعًا جديدًا وسمّه Lesson08_01، ضع الصنفين السابقين بجوار الصنف Program ضمن فضاء الاسم Lesson08_01 ثم اكتب الشيفرة التالية ضمن التابع Main: Child c = new Child(); c.MyMethod(); نفّذ البرنامج لتحصل على الخرج التالي: Father: In Constructor Father: In MyMethod من الواضح أنّ التنفيذ سيدخل إلى بانية الصنف Father (تذكّر أنّ البانية هي أوّل تابع يُستدعى عند إنشاء الكائن) وإلى التابع MyMethod وكلاهما موجودان ضمن الصنف الأب Father. لنضيف بعض التعديلات على الصنف Child. عدّل الصنف Child ليصبح كما يلي: class Child : Father { public Child() { Console.WriteLine("Child: In Constructor"); } } لاحظ أنّنا قد أضفنا بانية عديمة الوسائط للصنف Child وبداخلها التابع WriteLine لطباعة جملة توضيحيّة. أعد تنفيذ البرنامج السابق لتحصل على الخرج التالي: Father: In Constructor Child: In Constructor Father: In MyMethod الخرج السابق منطقيّ تمامًا. عند إنشاء كائن من الصنف Child باستخدام العبارة: Child c = new Child(); فإنّ بانية الصنف Child سُتستدعى نتيجة لذلك، وبما أنّ الصنف Child يرث من الصنف Father لذلك فإنّ بانية الصنف Father هي من ستُنفّذ أولًا ومن ثمّ بانية الصنف Child. أمّا عند استدعاء التابع MyMethod من الكائن الموجود ضمن المتغيّر c فسنحصل على رسالة الخرج الثالثة كما هو متوقّع. لنجرّب الآن شيئًا آخر. ماذا لو أردنا استبدال محتوى التابع MyMethod بمحتوى خاص بالابن، بمعنى آخر نريد "تجاوز" تعريف التابع MyMethod الموجود في الصنف الأب Father إلى تعريف آخر للتابع MyMethod ولكنّه خاص بالصنف Child. أضف التابع التالي إلى الصنف Child: public new void MyMethod() { Console.WriteLine("Child: In MyMethod"); } لاحظ وجود الكلمة المحجوزة new بعد مُحدّد الوصول public. وظيفة هذه الكلمة في هذا المكان هي إخفاء التابع MyMethod الموجود في الصنف Father واستبداله بالتابع MyMethod الموجود في الصنف Child. الآن بعد تنفيذ البرنامج ستحصل على الخرج التالي: Father: In Constructor Child: In Constructor Child: In MyMethod تمّ المطلوب، لقد أُخفي التابع MyMethod الموجود ضمن الصنف الأب Father لصالح التابع MyMethod الموجود ضمن الصنف الابن Child. يجب أن يبدو البرنامج Lesson08_01 بعد التعديلات الأخيرة شبيهًا بما يلي: 1 using System; 2 3 namespace Lesson08_01 4 { 5 class Father 6 { 7 public Father() 8 { 9 Console.WriteLine("Father: In Constructor"); 10 } 11 12 public void MyMethod() 13 { 14 Console.WriteLine("Father: In MyMethod"); 15 } 16 } 17 18 class Child : Father 19 { 20 public Child() 21 { 22 Console.WriteLine("Child: In Constructor"); 23 } 24 25 public new void MyMethod() 26 { 27 Console.WriteLine("Child: In MyMethod"); 28 } 29 } 30 31 class Program 32 { 33 static void Main(string[] args) 34 { 35 Child c = new Child(); 36 37 c.MyMethod(); 38 39 } 40 } 41 } محدد الوصول protected يُستخدم محدّد الوصول protected في الوراثة. فعندما نُعرّف أحد أعضاء الصنف الأب باستخدام protected فهذا يعني أنّه لا يمكن الوصول إليه مطلقًا إلّا من خلال أعضاء الصنف الأب نفسه، أو من خلال أعضاء الصنف الابن (أو الأحفاد). 1 using System; 2 3 namespace Lesson08_02 4 { 5 class Car 6 { 7 protected string manufacturer; 8 9 public Car() 10 { 11 this.manufacturer = "Car"; 12 } 13 14 public string Manufacturer 15 { 16 Get 17 { 18 return this.manufacturer; 19 } 20 } 21 } 22 23 class Toyota : Car 24 { 25 public Toyota() 26 { 27 this.manufacturer = "Toyota"; 28 } 29 } 30 31 class Program 32 { 33 static void Main(string[] args) 34 { 35 Toyota toyota = new Toyota(); 36 37 Console.WriteLine(toyota.Manufacturer); 38 } 39 } 40 } عند تنفيذ البرنامج ستحصل على الكلمة Toyota في الخرج. السبب في ذلك أنّ بانية الصنف Toyota تصل إلى الحقل manufacturer في السطر 27، رغم أنّه مصرّح عنه في الصنف الأب Car، وذلك لأنّه ذو محدّد وصول protected. من الواضح أنّ الأعضاء المصرّح عنها باستخدام محدّد الوصول private في الأصناف الآباء تبقى مرئيّةً فقط ضمن أعضاء الصنف الأب فحسب. التعددية الشكلية Polymorphism سبق وأن تحدّثنا عن التعدديّة الشكليّة، وكيف أنّها مفهوم أساسيّ في البرمجة كائنيّة التوجّه. يتمحور مفهوم التعدديّة الشكليّة حول أنّه يحق للصنف الابن إعادة صياغة تابع (أو خاصيّة) موجود في صنف أب بصورةٍ تناسبه أكثر. لقد طبّقنا هذا المفهوم قبل قليل وذلك عندما "تجاوز" التابع MyMethod في الصنف الابن Child، التابع MyMethod الموجود في الصنف الأب Father، فأصبح التابع الموجود في الابن يُعبّر عن نفسه بشكل أكثر تخصّصًا. ولكن هذه ليست هي الطريقة المثلى لتنفيذ فكرة التعدديّة الشكلية، تزوّدنا سي شارب في الواقع بأسلوب أفضل بكثير لتحقيق هذا المفهوم. هل تذكر مثال الضفدع Frog والسمكة Fish والطائر Bird وسلوكيّة الانتقال Move التي يرثونها من الصنف Animal؟ تناولنا هذا المثال البسيط في درس سابق. وقد ذكرنا أنّ الصنف Animal هو الصنف الأب للأصناف Frog و Fish و Bird وهو يحتوي على التابع Move الذي يُعبّر عن سلوكيّة الانتقال. وبما أنّ كلًّا من الأصناف الأبناء الثلاثة تُعبّر بشكل مختلف عن عمليّة الانتقال، لذلك فنحن أمام التعدديّة الشكليّة. يحتوي البرنامج Lesson08_03 على صنف أب Animal يحوي تابعًا وحيدًا اسمه Moveـ موسوم بالكلمة المحجوزة virtual التي تجعل منه تابعًا ظاهريًّا يسمح للتوابع الأخرى بتجاوزه. بالإضافة إلى وجود ثلاثة أصناف أبناء للصنف Animal وهي Frog و Fish و Bird. يحتوي كل صنف من الأصناف الأبناء على التابع Move مع وسم خاص هو override. تسمح هذه الكلمة للتابع في الصنف الابن أن "يتجاوز" تعريف نفس التابع في الصنف الأب (موسوم بالكلمة virtual). أعني بكلمة "تجاوز" إعادة تعريف التابع بالشكل الذي يناسب الصنف الابن. فعند الحديث عن الانتقال، فالذي يناسب الضفدع Frog هو القفز، والذي يناسب السمكة Fish هو السباحة، والذي يناسب الطائر Bird بالطبع هو الطيران. وبالمناسبة فإنّ التابع ToString الموجود في الصنف Object هو تابع ظاهريّ (موسوم بالكلمة virtual) ليسمح لأي صنف آخر بتجاوزه. إليك الآن البرنامج Lesson08_03: 1 using System; 2 3 namespace Lesson08_03 4 { 5 class Animal 6 { 7 public virtual void Move() 8 { 9 Console.WriteLine("Animal: Move General Method"); 10 } 11 } 12 13 class Frog : Animal 14 { 15 public override void Move() 16 { 17 Console.WriteLine("Frog - Move: jumping 20 cm"); 18 } 19 } 20 21 class Bird : Animal 22 { 23 public override void Move() 24 { 25 Console.WriteLine("Brid - Move: flying 10 m"); 26 } 27 28 } 29 30 class Fish : Animal 31 { 32 public override void Move() 33 { 34 Console.WriteLine("Fish - Move: swimming 1 m"); 35 } 36 } 37 class Program 38 { 39 static void Main(string[] args) 40 { 41 Frog frog = new Frog(); 42 Fish fish = new Fish(); 43 Bird bird = new Bird(); 44 45 frog.Move(); 46 fish.Move(); 47 bird.Move(); 48 } 49 } 50 } نفّذ البرنامج السابق لتحصل على الخرج التالي: Frog - Move: jumping 20 cm Fish - Move: swimming 1 m Brid - Move: flying 10 m لاحظ كيف يُعبّر كلّ كائن من الأصناف الأبناء عن التابع Move بالشكل الذي يناسبه. وواضح أنّ التابع Move الموجود في الصنف الأب Animal لا يُستدعى مطلقًا. ولكن في بعض الحالات قد نرغب أن يُستدعى التابع المُتجاوَز الموجود في الصنف الأب لإنجاز بعض المهام ومن ثمّ نتابع العمل ضمن التابع المُتجاوِز. يمكننا ذلك ببساطة من خلال استخدام الكلمة المحجوزة base التي تُشير إلى الصنف الأب الذي يرث منه الابن. لاستدعاء التابع Move الموجود في الصنف الأب Animal وذلك من خلال التابع Move الموجود في الصنف Frog أضف العبارة التالية بعد السطر 16 مباشرةً قبل أي عبارة أخرى، ليصبح هذا التابع على الشكل: public override void Move() { base.Move(); Console.WriteLine("Frog - Move: jumping 20 cm"); } أعد تنفيذ البرنامج لتحصل على الخرج التالي: Animal: Move General Method Frog - Move: jumping 20 cm Fish - Move: swimming 1 m Brid - Move: flying 10 m انظر كيف استُدعي التابع Move الموجود في الصنف الأب Animal ومن ثمّ استُدعي التابع Move الموجود في الصنف الابن Frog. التحويل بين الأنواع سنتناول في هذه الفقرة سلوكًا قد يبدو غريبًا بعض الشيء، ولكنّه مهم وأساسيّ وسيصادفك في معظم البرامج التي تكتبها باستخدام سي شارب. أعد البرنامج Lesson08_03 إلى حالته الأصلية (أي أزل العبارة ()base.Move). امسح محتويات التابع Main واستبدلها بالشيفرة التالية: Animal animal = new Frog(); animal.Move(); العبارة الأولى غريبة قليلًا أليس كذلك؟ في الحقيقة الوضع طبيعي تمامًا، فبما أنّ الصنف Animal هو صنف أب للصنف Frog لذلك فيستطيع أيّ متغيّر مصرّح عنه على أنّه من النوع Animal (في مثالنا هذا هو المتغيّر animal) أن يخزّن مرجع إلى كائن من الصنف Frog (تذكّر أنّ التعبير ()new Frog يولّد مرجع لكائن من الصنف Frog). نفّذ البرنامج الآن لتحصل على الخرج التالي: Frog - Move: jumping 20 cm يبدو أنّ برنامجنا ذكيّ كفاية لكي يعرف أنّ الكائن الذي يشير إليه المتغيّر animal هو كائن من الصنف Frog. في الحقيقة يحصل هنا تحويل ضمني بين الكائنات، ولكن إذا فعلنا العكس، أي أسندنا مرجع لكائن من الصنف Animal إلى متغيّر من النوع Frog فسنحصل على خطأ أثناء ترجمة البرنامج. امسح محتويات التابع Main واستبدلها بالشيفرة التالية: Animal animal = new Frog(); Frog frog = animal; نحاول في السطر الثاني أن نُسند المتغيّر animal من النوع Animal إلى المتغيّر frog من النوع Frog، فنحصل على الخطأ التالي عند محاولة تنفيذ البرنامج: Cannot implicitly convert type 'Lesson08_03.Animal' to 'Lesson08_03.Frog'. An explicit conversion exists (are you missing a cast?) يخبرنا هذا الخطأ أنّه لا يمكن التحويل بشكل ضمنيّ من النوع Animal إلى النوع Frog ويقترح علينا استخدام عامل التحويل بين الأنواع casting (هل تذكره؟). رغم أنّ المتغيّر animal يحمل مرجع إل كائن من الصنف Frog في حقيقة الأمر (انظر السطر الأوّل من الشيفرة السابقة) إلّا أنّنا عند محاولتنا إسناد المتغيّر animal إلى المتغيّر frog حصلنا على خطأ. السبب في ذلك هو أنّه لا يحدث تحويل ضمنيّ بين الأنواع implicit conversion وإنّما يتطلّب الأمر إجراء تحويل صريح باستخدام عامل التحويل بين الأنواع. إذا استبدلت السطر الثاني من الشيفرة السابقة بالسطر التالي، ستكون الأمور على ما يرام: Frog frog = (Frog)animal; لاحظ كيف وضعنا عامل التحويل (Frog) أمام المتغيّر animal. سيضمن ذلك حدوث التحويل المطلوب دون أيّ مشاكل. لكي تريح نفسك من التفكير متى يحدث التحويل الضمنيّ ومتى يجب استخدام التحويل الصريح، تذكّر منّي القاعدة التالية: "في حياتنا اليوميّة، كثيرًا ما يحتوي الأب ابنه، ولكنّ العكس ليس صحيحًا". أعلم أنّ لهذه القاعدة شواذ في واقعنا، ولكنّها في البرمجة لا تخيب! فالمتغيّر من النوع الأب يستطيع استقبال أي مرجع لكائن من صنف ابن، ولكنّ العكس ليس صحيح ما لم نستخدم التحويل الصريح بين الأنواع. تحدث ظاهرة التحويل بين الأنواع بالنسبة للأنواع المضمّنة built-in أيضًا. فهناك تحويلات تحدث ضمنيًّا، وأخرى تحدث بتدخّل من المبرمج باستخدام عامل التحويل بين الأنواع، ولكن مع فرق جوهريّ. ففي هذه الحالة ليس بالضرورة أن يكون بين الأنواع التي تجري عمليّة التحويل فيما بينها أي علاقة وراثة. فمثلًا يمكن التحويل ضمنيًّا بين متغيّر من النوع int إلى آخر من النوع double: int i = 6; double d = i; أمّا إذا حاولنا فعل العكس: double d = 6; int i = d; فسنحصل على نفس الخطأ السابق الذي يخبرنا بوجوب استخدام التحويل الصريح بين الأنواع. يمكن حل هذه المشكلة ببساطة باستخدام عامل التحويل (int) ووضعه أمام المتغيّر d في السطر الثاني: double d = 6; int i = (int)d; نخبر المترجم هنا أنّنا نريد التحويل فعليًّا من double إلى int. ستحتاج إلى مثل هذه التقنيّة دومًا إذا كانت عمليّة التحويل ستؤدّي إلى ضياع في البيانات. فالتحويل من double إلى int سيؤدّي إلى ضياع القيمة على يمين الفاصلة العشريّة لأنّ المتغيّرات من النوع int لا تقبلها. وكذلك الأمر عند التحويل من float إلى double لأنّ المتغيّرات من النوع float ذات دقّة أقل من المتغيّرات من النوع double، وهكذا. تمارين داعمة تمرين 1 عدّل البرنامج Lesson08_03 ليعمل كل صنف من الأصناف Frog و Bird و Fish على تجاوز التابع ToString (الموجود في الصنف الأب Object). بحيث عند استدعاء التابع ToString من كائن من الصنف Frog نحصل على النص "I am Frog"، وهكذا بالنسبة للصنفين الباقيين كلّ حسب اسمه. تمرين 2 استفد من البرنامج Lesson08_02 في إنشاء صنف جديد اسمه Corolla يرث من الصنف Toyota. وأضف إلى الصنف الجديد الخاصيّة ProductionYear من النوع int. بعد ذلك أنشئ كائنًا من الصنف Corolla وحاول إسناد قيم لهذه الخاصيّة، وقرائتها منها. الخلاصة تعرّفنا في هذا الدرس على كيفيّة تطبيق الوراثة في سي شارب، كما تعرّفنا على مبادئ التعدديّة الشكليّة Polymorphism وأهميّتها وكيفيّة استثمارها في هذه اللغة. وتعاملنا أيضًا مع التحويل بين الأنواع ورأينا كيف يمكن لمتغيّر من صنف أب أن يحمل مراجع لكائنات من أصناف أبناء. تُستَخدم هذه الأساليب على نحو واسع جدًّا في مكتبة الأصناف الأساسيّة، وستحتاجها في العديد من التطبيقات التي تُنشئها.
×
×
  • أضف...