السلام عليكم ورحمة الله وبركاته
في هذا الرد سنوضح الفرق بين الـ Interface والـ Class من ناحية الوراثة ـ
بينما بقية المقارنات مشروحة في الردود تحت بواسطة الاعضاء الكرام ..
احيانا نحتاج الى استعمال مبدأ الوراثة ، ولكن معظمنا لايعرف ماذا يستخدم للوراثة ، هل يستخدم الـ Interface او يستخدم الـ Class ؟
ولكن المقالة التالية ستوضح بشكل قاطع متى يستخدم الـ Class ومتى يستخدم الـ Interface
سؤال / متى استخدم الوراثة من كلاس (Inheritance from Base Class) ومتى استخدم الوراثة من الواجهات البرمجية(Inheritance from Interface) ؟
او ممكن اعادة صياغة السؤال بضمير المتحدث :-
سؤال / انا بحاجة لتطبيق مبدأ الوراثة ، فهل اقوم بانشاء Base Class او اقوم بانشاء Interface ؟
-----------------------------------------------
الجواب :- المفهومان يتشابهان الى حد كبير لدرجة انك احيانا لا تعلم ايهما تستخدم .. لذلك وجدت العلاقة التالية التي تحدد لك بوضوح ايهما يجدر استعماله :-
العلاقة الاولى : Is-a ، عندما تكون لدينا هذه العلاقة بين اثنين Types ، هنا نقوم بانشاء Base Class ونقوم بالاشتقاق منها ((Inheritance from Base Class)
العلاقة الثانية : can-do ـ عندما تكون لدينا هذه العلاقة بين اثنين Types ، هنا نقوم بانشاء واجهة برمجية ونقوم بالاشتقاق منها (Inheritance from Interface)
--
مثال من مكتبات ال.NET ... هناك كلاس اسمه
Bitmap ، هذا الكلاس مشتق من الكلاس
Image
لماذا قام مصمم اللغة بتعريف Class باسم Image ؟، لماذا لم يقم بتعريف Image كـ Interface ؟
السبب لان العلاقة المستخدمة بين الكلاسين هي
Is-a >>
Bitmap Is an Image
وفي نفس الوقت ، الكلاس Bitmap مشتق كذلك من واجهة برمجية تسمى
IDisposable وايضا من واجهة اخرى تسمى
ICloneable
لماذا قام مصمم اللغة بتعريف Interface باسم IDisposable ، لماذا لم يقم بتعريف IDisposable كـ Class ؟
لان العلاقة المستخدمة هنا
can-do >>
Bitmap can do Dispose
Bitmap can do Clone
اذن الشكل العام للكلاس Bitmap سيكون كالتالي :-
PHP كود :
public class Bitmap : Image , IDisposable , ICloneable
{
}
--
مثال اخر/ انظر هذا الكود :-
PHP كود :
class Ahmed : Person, IWalk, ISleep, ISwim
{
}
في الكود السابق هناك كلاس باسم
Ahmed وهو يشتق من Base Class المسمى
Person ، ويشتق ايضا من
ثلاثة Interface
السبب في اشتقاق Ahmed من الكلاس Person
هو وجود علاقة
Is-a >>
ِAhemd is a Person
بينما السبب في الاشتقاق من الInterfaces المسميات
IWalk و IEat و ISleep
هو وجود العلاقة
can-do >>
Ahmed can walk
Ahmed can eat
Ahmed can sleep
لذلك يجب ان تُعرًف Person كـ Class ، لانها تحقق علاقة Is- a
بينما يجب عليك ان تُعرًف IWalk و IEat و ISleep كـ Interface ، لانهم يحققون علاقة can- do
وهذا كود تعريفهم :-
PHP كود :
//base class
class Person
{
}
//interfaces
interface IWalk
{
}
interface IEat
{
}
interface ISleep
{
}
--
الخاتمة :-
دائما عندما تقوم بكتابة اكوادك وعندما تكون بحاجة لاستعمال مبدأ الوراثة ، يجدر بك ان تعرف متى تقوم بانشاء Interface و متى تقوم بانشاء Base Class وذلك باستخدام العلاقتين اعلاه .
تحياتي[/b]
(29-06-16, 02:15 AM)ابو ليلى كتب : [ -> ]^
جزاك الله خيرا على هذه المداخلة القيمة
هذا الرد بمثابة درس كامل عن الInterface
بارك الله فيك
--
بقي شيئ واحد اعتقد يجب توضيجه للجميع بخصوص الInterface
ماهي الفائدة العملية من الـ Interface ؟
كنت حاب اجاوب على هذا السؤال ، لكن مو وقته حاليا

..
^
يامحاسن الصدف ...
انا ايضا تعاملت مع الPlugin بالـ Reflector
ولكن ليس باستعمال الـ Interface بل باستعمال الـ Abstract class (اخت الـ Interface بالرضاعة

)
والسبب في ذلك ان الInterface لاتدعم كتابة المتغيرات بداخلها ، وهذا سبب لي مشكلة
مثلا كنت اريد اضافة متغير Name بهذا الشكل
PHP كود :
interface IPlugin
{
public string Name
}
الا اننا نعرف ان الكود اعلاه بيسبب مشكلة ، لان الInterface لاتدعم ذلك
وحتى لو قمت بتحويل Name الى Property سيبب ذلك مشكلة وهو انني سأضطر الى اعادة تعريف للخاصية في الكلاس الجديد (بالعربي ، مااستفدت شيئ

)
بالاضافة الى ذلك ، لو طبقنا العلاقتين المذكورتين بالموضوع ، سنجد ان علاقة Is- a هي التي تصلح لموضوع الPlugin
لو عرفت Plugin باسم MyPlugin فيجب ان تستورث من
Class لان العلاقة ستصبح >>>
MyPlugin Is a Plugin
MyPlugin can Plugin(لغويا غير ممكنة ، لذلك العلاقة لاتصلح)
اذن العلاقة هي Is- A فيجب الاشتقاق من Class .. ولكن المشكلة بالـ classes العادية ان اكوادها ثابتة ولاتناسب موضوع الPlugin لاننا نحتاج الى Type يمكننا من عمل Re-Implemented لاستعماله كقالب
للcasting او لاستعماله في
Plugin اخرى ..
ولكن -لحسن الحظ- Abstract class هو المنقذ

[/b]
PHP كود :
abstract class PluginBase
{
public string Name { get; set; }
public string Author { get; set; }
public abstract void Load();
}
//plugins
public class MyPlugin : PluginBase
{
public MyPlugin()
{
this.Name = "Sound Plugin v1.0";
this.Author = "Vb4arb";
}
public override void Load()
{
//my staff
}
}
public class BrotherPlugin : PluginBase
{
public BrotherPlugin()
{
this.Name = "Video Plugin v1.0";
this.Author = "google";
}
public override void Load()
{
//brother staff
}
}
أساتذة اجتمعوا في موضوع........
السلام عليكم
جزاكم الله خيرا على هذا النقاش الجميل
أحب أن اضيف بعض المعلومات بخصوص الـ interface
لا يمكن انشاء instance من interface
لا يمكن استخدام الـ (Access Specifiers ) محددات الوصول(public, private ) عند تعريف الدوال داخل الـ interface لأنها public by default
PHP كود :
interface IC
{
public void Print(); // Error
}
الصحيح
PHP كود :
interface IC
{
void Print(); // هذا هو التصريح الصحيح للدالة بدون استخدام محددات الوصول
}
لذا عند استخدام الدوال في الـ class سيكون عليك لزاماً أن تعرف الدوال كــ public في الclass وإن لم تفعل ذلك سخبركك المترجم بأن هنالك خطأ
PHP كود :
class A : IC
{
void Print() // Error
{
Console.Write("Hello");
}
}
الصحيح
PHP كود :
class A : IC
{
public void Print()
{
Console.Write("Hello");
}
}
يمكن لــ interface أن يرث من interface آخر
في حال تعريف دالة داخل الــ interface سيكون لزاماً عليك استخدامها في الـ class التي يرث من الـ interface
طيب ماذا لو كان لدينا class ورث من اثنين interface وكلا الـ interface يحتويان نفس الدالة حتى لو كانت الدوال لها وظائف مختلفة؟ بالشكل التالي:
PHP كود :
interface IC
{
void Print();
}
interface IB
{
void Print();
}
لذا يتم حل المشكلة بالشكل التالي:
PHP كود :
class A : IB, IC
{
void IC.Print()
{
Console.Write("Hello C");
Console.ReadKey();
}
void IB.Print()
{
Console.Write("Hello B");
Console.ReadKey();
}
}
في هذه الحالة الدوال تعرف على أنها private by default
طيب كيف سيكون استدعاء الدوال؟
الجواب: سنستخدم هنا Explicit interface بالشكل التالي:
لأن الدوال private فلا يمكن الوصول اليها إلا باستخدام Explicit interface
PHP كود :
private static void Main()
{
var a = new A();
((IC) a).Print();
((IB) a).Print();
}
تحياتي لكم
شكرا للاخ سجاد على المداخلة القيمة ، وشكرا للاخ امير الزبيدي على المشاركة والتشجيع
يبدو ان مواضيع الـ OOP تعجبكم
اذن اليوم مقالة اخرى ان شاء الله
كما قال اخونا "امير الزبيدي"
هذا الموضوع لازم يتغير عنوانه
لان هذي المعلومات لازم الكل يشوفها ويتعلم منها ..
بالنسبة الى Sealed Class ابدا لم اتعامل معها
