تقييم الموضوع :
  • 1 أصوات - بمعدل 5
  • 1
  • 2
  • 3
  • 4
  • 5
[نقاش] الفرق بين الـ Interface , Abstract Class , Base Class , Sealed Class
#1
السلام عليكم ورحمة الله وبركاته




في هذا الرد سنوضح الفرق بين الـ 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 PersonIWalkISleepISwim
   
{
   





في الكود السابق هناك كلاس باسم 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]
الرد }}}
#2
كلام جميل اخي الشاكي و خصوصا عندما تريد عمل مبدأ الوراثة المتعددة 
كما تعلم الوراثة المتعددة غير مدعومة في عملنا على #C 

لذلك اتى مبدأ تطبيق الواجهات حل سحري لتلافي القصر  Implement Interfaces



مثلا لو كان لدي كلاسين كما يلي


PHP كود :
Class FirstClass { }
 
   Class SecondClass { } 

فانني لن استطيع تطبيق ما يلي
PHP كود :
class NewClass FirstClassSecondClass  { } 
بينما لو كان لدي واجهتين كما يلي
PHP كود :
interface { }
    interface 
{ } 


يصبح من السهل علي الاستفادة منهما كما يلي

PHP كود :
class NewClass X{ } 

كما يمكنني ايضا وراثة الكلاس و تطبيق الواجهة في نفس الوقت كما يلي
PHP كود :
class NewClass FirstClass{ } 


و بقيت الاشارة الى ان  Interface    



تحتوي فقط على على طرق و خصائص و متغيرات بدون كود فقط تمهيد لها

و باعادة تطبيقها يمكنك كتابة الاكواد المناسبة لهذه الطرق كما تشاء.

بعكس Class الذي يحتوي على كل شيئ.
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
#3
(29-06-16, 02:15 AM)ابو ليلى كتب : ^

جزاك الله خيرا على هذه المداخلة القيمة

هذا الرد بمثابة درس كامل عن الInterface Big Grin

بارك الله فيك


--


بقي شيئ واحد اعتقد يجب توضيجه للجميع بخصوص الInterface
ماهي الفائدة العملية من الـ Interface ؟


كنت حاب اجاوب على هذا السؤال ، لكن مو وقته حاليا Undecided ..
الرد }}}
تم الشكر بواسطة: Amir_Alzubidy , ابو ليلى , الوادي
#4
الفوائد كثيرة اخي و خصوصا اذا كنت من اصحاب الطرق التوسعية  Big Grin
انا استخدمتها في تقنية Plugins لتوظيف طرق جديدة داخل التطبيق
و العملية جدا ممتعة و رهيبة من خلال Interfaces
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
#5
^
يامحاسن الصدف ...

انا ايضا تعاملت مع الPlugin بالـ Reflector
ولكن ليس باستعمال الـ Interface بل باستعمال الـ Abstract class (اخت الـ Interface بالرضاعة Big Grin)

والسبب في ذلك ان الInterface لاتدعم كتابة المتغيرات بداخلها ، وهذا سبب لي مشكلة
مثلا كنت اريد اضافة متغير Name بهذا الشكل

PHP كود :
   interface IPlugin
   
{
       public string Name 
   



الا اننا نعرف ان الكود اعلاه بيسبب مشكلة ، لان الInterface لاتدعم ذلك
وحتى لو قمت بتحويل Name الى Property سيبب ذلك مشكلة وهو انني سأضطر الى اعادة تعريف للخاصية في الكلاس الجديد (بالعربي ، مااستفدت شيئSad)


بالاضافة الى ذلك ، لو طبقنا العلاقتين المذكورتين بالموضوع ، سنجد ان علاقة Is- a هي التي تصلح لموضوع الPlugin
لو عرفت Plugin باسم MyPlugin فيجب ان تستورث من Class لان العلاقة ستصبح >>>
MyPlugin Is a Plugin Smile
MyPlugin can Plugin(لغويا غير ممكنة ، لذلك العلاقة لاتصلح)


اذن العلاقة هي  Is- A  فيجب الاشتقاق من Class  .. ولكن المشكلة بالـ classes  العادية ان اكوادها ثابتة ولاتناسب موضوع الPlugin لاننا نحتاج الى Type يمكننا من عمل Re-Implemented لاستعماله كقالب للcasting او لاستعماله في Plugin اخرى ..

ولكن -لحسن الحظ- Abstract class هو المنقذ Smile[/b]
PHP كود :
   abstract class  PluginBase
    
{
 
       public string Name getset; }
 
       public string Author getset; }
 
       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
 
       }
 
   
الرد }}}
#6
أساتذة اجتمعوا في موضوع........
الرد }}}
تم الشكر بواسطة: Amir_Alzubidy , الشاكي لله , ابو ليلى
#7
اخي الوادي فعلا سبقتني
لو كنت امتلك صلاحية تغيير عنوان الموضوع
لكتبت " لقاء العمالقة و ال Interface "
الرد }}}
#8
السلام عليكم

جزاكم الله خيرا على هذا النقاش الجميل

أحب أن اضيف بعض المعلومات بخصوص الـ interface



لا يمكن انشاء instance من interface
PHP كود :
IC c=new IC(); // Error 
لا يمكن استخدام الـ (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 IC
    
{
 
       void Print() // Error
 
       {
 
           Console.Write("Hello");
 
       }
 
   

الصحيح

PHP كود :
class IC
    
{
 
       public void Print() 
 
       {
 
           Console.Write("Hello");
 
       }
 
   

يمكن لــ interface أن يرث من interface آخر

PHP كود :
interface IB IC
    
{
 
       
    


في حال تعريف دالة داخل الــ interface سيكون لزاماً عليك استخدامها في الـ class التي يرث من الـ interface


طيب ماذا لو كان لدينا class ورث من اثنين interface وكلا الـ interface يحتويان نفس الدالة حتى لو كانت الدوال لها وظائف مختلفة؟ بالشكل التالي:
PHP كود :
interface IC
    
{
 
       void Print();
 
   }

 
   interface IB
    
{
 
       void Print();
 
   

لذا يتم حل المشكلة بالشكل التالي:

PHP كود :
class IBIC
    
{
 
       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();
 
           ((ICa).Print();
 
           ((IBa).Print();
 
       

تحياتي لكم
الرد }}}
#9
اتلذذ بقراءة مثل هذه المقالات والردود الراقية
ما شاء الله عليكم
واتمنى من مشرفين القسم تثبيت المقال
الرد }}}
#10
شكرا للاخ سجاد على المداخلة القيمة ، وشكرا للاخ امير الزبيدي على المشاركة والتشجيع

يبدو ان مواضيع الـ OOP تعجبكم Smile


اذن اليوم مقالة اخرى ان شاء الله
الرد }}}
تم الشكر بواسطة: Sajad , Amir_Alzubidy


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [نقاش] نقاش حول تطبيق الفاتورة الإلكترونية فى السعودية المرحلة الثانية Zatca Integration AmrSobhy 2 1,598 26-01-23, 09:09 PM
آخر رد: AmrSobhy
  تعلم Interface Abu Ehab 1 2,060 19-02-18, 10:38 PM
آخر رد: sendbad100
  KeyValuePair Class Abu Ehab 1 2,016 16-12-17, 06:08 PM
آخر رد: sendbad100
  ZipFile Class Abu Ehab 1 2,263 18-11-16, 03:44 AM
آخر رد: abulayth
  [نقاش] الـ Delegate الشاكي لله 12 9,070 01-09-16, 02:27 AM
آخر رد: أبو عمر
  [C#.NET] الفرق بين #String And String Builder c Devahmedsalim 3 4,569 15-09-13, 05:50 PM
آخر رد: sooriaty03
  Tips and Tricks : الفرق بين const و static readonly RaggiTech 0 3,248 14-10-12, 03:05 PM
آخر رد: RaggiTech
  الفرق بين التعريف باستخدام overridde و new RaggiTech 0 2,861 14-10-12, 02:57 PM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم