تقييم الموضوع :
  • 1 أصوات - بمعدل 5
  • 1
  • 2
  • 3
  • 4
  • 5
[نقاش] الفرق بين الـ Interface , Abstract Class , Base Class , Sealed Class
#11
الشكر لله
يسرني ذلك لانه قريبا سادخل عالمكم ان شاء الله
و لا بد استفيد من هذه المقالات
[+1]
الرد }}}
تم الشكر بواسطة: Sajad , Sajad , rnmr , rnmr
#12
انتظر..... حتى افرغ ما لدي بطريقة اخرى 
هذا النقاش اللذيذ كما اشار الاخ امير يعجبني 
وما دام الاخوة يقدمون الافضل و الاجمل لذا اصبح حق علي ان اشرح ما سبق بطريقتي  Big Grin
 و اتمنى ان تعجبكم

الشرح استكمال لافكار كل الاخوة في المقال جزاهم الله كل خير و اثابهم الجنة.

مع توسع قليل من قبلي

اولا ان النوع   abstract class   يسمح بالتوريث من الكلاسات الاخرى (اي ترث منه الكلاسات الاخرى)   

ولا يمكنك انشاء نسخة مباشرة منه instantiated.

ويجب الاشارة الى ان هذا النوع يجب ان يمتلك على الاقل واحدة او اكثر من الطرق  المكتملة (اي تحتوي على كود ساسميه جسم الدالة)
و كذلك على الاقل طريقة واحدة غير مكتملة اي بدون جسم للدالة , و يجب تعريفها بالمحدد abstract

اذا كانت كل الطرق في الكلاس غير مكتملة عندها تصبح شبيهة بـ interface

ثانيا الواجهات Interface

يتم تعريفها بالكلمة المفتاحية interface و هي تحتوي على دوال غير مكتملة اي لاتحوي على جسم (تمهيد فقط)
اما عن الفائدة منها فهو في الكلاس التي ستطبق و تستفيد من هذه الطرق بعد ان تكون قد ورثت interface السابقة
و جميع الطرق و الخصائص داخل interface  كما قال الاخ سجاد هي بشكل افتراضي عامة Puplic
ساقوم بالشرح وفق الاكواد لتسهيل المهمة و لاعطاء الشرح هدف واضح
طبعا انا ساكتب اكواد #C لان المقالة في هذا القسم بالتحديد (بالنسبة لاكواد #C انا اكتبها بحكم عملي على الجافا )
لننظر الى الكود التالي الذي يعرف كلاس بسيطة من النوع abstract Class 


PHP كود :
public abstract class Product
{
 
 //fields
 
 protected string id;
 
 protected double price;
 
 //properties
 
 public abstract string ID
  
{
 
   get;
 
   set;
 
 }
 
 
 public abstract double Price
  
{
 
   get;
 
   set;
 
 
 }
 
 public abstract double CalculatePrice();


الكلاس بسيط يحتوي على حقلين مع خصائص لكل حقل  ويحتوي على طريقة واحدة تعيد المجموع


و لدي ايضا interface  يحتوي على خاصيتين و نفس الدالة السابقة


PHP كود :
public interface Iproduct
{
 
 string ID
  
{
 
   get;
 
   set;
 
 
 }
 
 
 double Price
  
{
 
   get;
 
   set;
 
 
 }
 
 double CalculatePrice();


وجه الخلاف اننا لا نستطيع تعريف متغيرات بشكل مباشر ضمن interface  كما اشار الاخ الشاكي سابقا

الان ساقوم بانشاء كلاس يقوم بتطبيق الواجهة  Iproduct (سيتم تطبيق كل الخصائص و الطرق الموروثة هذا شرط اساسي)


PHP كود :
public class implementInterfaceIproduct
{
 
 protected string id;
 
 protected double price;
 
 public string ID
  
{
 
   get
    
{
 
     return id;
 
   }
 
   set
    
{
 
     id value;
 
   }
 
 }
 
 public double price
  
{
 
   get
    
{
 
     return price;
 
   }
 
   set
    
{
 
     price value;
 
   }
 
 
 }
 
 public double CalculatePrice()
 
 {
 
   return Price 1.25;
 
 


هل رايت كيف تم توسيع الطرق و الخصائص (هكذا تستفيد من اعادة التطبيق )

الان اريد التطبيق على الكلاس Product و هو من النوع abstract Class 
لدينا هنا كلاس جديد يقوم بوراثة الكلاس السابق Product و يعيد قيادة الطرق و الخصائص كما يلي

PHP كود :
public class implementAbstractProduct
{
 
 public override string ID
  
{
 
   get
    
{
 
     return id;
 
   }
 
   set
    
{
 
     id value;
 
   }
 
 
 }
 
 public override double Price
  
{
 
   get
    
{
 
     return price;
 
   }
 
   set
    
{
 
     price value;
 
   }
 
 
 }
 
 public override double CalculatePrice
  
{
 
   return Price 1.25;
 
 }
 



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

بعد ذلك يمكننا انشاء نسخة جديدة من الكلاس السابق implementAbstract و استخدمها في تطبيقنا كما يلي

PHP كود :
ImplementAbstract testAbstract = New implementAbstract();
testAbstract.ID="A1";
testAbstract.Price=1000.00;
Double amt testAbstract.CalculatePrice();
Response.Write("المجموع الصافي : " " " +testAbstract.ID +" ""is"+" "+amt);
Response.Write("<br>"); 


اماذا لو احببنا ان نستفيد من الكلاس  implementInterface الذي قام بتطبيق الواجه Iproduct 
نعم يمكننا ذلك كم عملنا سابقا انظر الكود

PHP كود :
ImplementInterface testInterface = New implementInterface();
testInterface.ID="B1";
testInterface.Price=900.00;
Double Iamt testInterface.CalculatePrice();
Response.Write("المجموع الصافي : " +" "+testInterface.ID +" ""is"+" "+Iamt);
Response.Write("<br>"); 


بقي ان اقول لك بان الاعضاء المشتركة المعرفة بالطريقة (Static) لا يمكن وراثتها تحت اي ظرف كان 
لذا نحن لا نستطيع تعريفها داخل Interface .
بينما يمكنك تعريف طرق مشتركة داخل الكلاسات من النوع abstract Class 

يمكننا اضافة الطريقة التالية الى الكلاس السابق Product 

PHP كود :
public static void test()
{


بينما لا يمكننا كتابتها في Interface 

اوجه الخلاف بين Abstract Class و Interfaces



  • Abstract Class يمكن ان تحتوي على طرق كا ملة و غير كاملة , بينما Interfaces لا تحتوي الا على طرق غير مكتملة فقط تمهيد للطرق بدون كود في جسم الدالة,لذا فان Abstract Class تستطيع تطبيق الطرق (implement) بينما Interface لا تستطيع ذلك.
  • Abstract Class يمكن ان تحتوي على متغيرات (حقول) , مشيدات , مهدمات - بينما Interfaces لا يمكن تحتوي على ما سبق .
  • Abstract Class لا تدعم الوراثة المتعددة , بينما Interfaces تدعم ذلك بقوة , اذ يمكنك ان تقوم بوراثة اكثر من Interfaces في نفس الكلاس مع امكانية ورائة كلاس فقط .
  • عندما ترث من Interface سيكون لزاما عليك تطبيق كل الطرق و الخصائص التي بداخل الـ Interface , بينما انت لست ملزما بتطبيق او اعادة قيادة كل الطرق عندما ترث من  النوع Abstract Class.
  • محددات الوصول مثل (Private,Public,Protected,internal,virtual) تستطيع استخدامها مع Abstract Class , و العكس ليس صحيح مع Interface .
  • اخيرا Abstract Class اسرع في التعامل من Interface .


بقي الحديث عن Sealed Class 

ليتضح معنى Sealed Class انظر معي لهذا الكلاس
PHP كود :
public sealed class classSealed
{
 
 public string ID;
 
 public double Price;



لا يمكن اعتبار هذا النوع فئة قاعدية (Base Class) و ليست ايضا من النوع Abstract Class  
هي تستخدم تحديدا لمنع اعادة اشتقاقها
و لانها ليست فئة قاعدية فان بعض معالجات النظام تستخدمها لتسريع عمليات الوصول الى الاعضاء بداخلها


لا يمكنك اعادة اشتقاقها و ايضا لا يمكنك اعادة قيادة الطرق بداخلها و لا يمكنك وراثتها ايضا

كيف يمكنني استخدامها اذاً , بكل بساطة انشأ نسخة منها و اسند القيم و استخدم الطرق بداخلها كما هي 



PHP كود :
classSealed sc=new classSealed();
sc.ID="C1";
sc.Price=500.00;
double Samt=scCalculatePrice(); 

بقي السؤال المطروح ايهما استخدم
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
#13
كما قال اخونا "امير الزبيدي"

هذا الموضوع لازم يتغير عنوانه

لان هذي المعلومات لازم الكل يشوفها ويتعلم منها ..



بالنسبة الى Sealed Class ابدا لم اتعامل معها Big Grin
الرد }}}
تم الشكر بواسطة: Sajad , Sajad , ابو ليلى , Amir_Alzubidy
#14
ماشاءالله

تم تثبيت الموضوع Smile

تحياتي لكم
الرد }}}
تم الشكر بواسطة: ابو ليلى , Amir_Alzubidy
#15
Abstract Classes تمكنك من اضافة الكثير من الوظائف للتطبيق بدون الاضرار بالكلاسات التي اشتقتها (انا اسميها الابناء)
اذ ان تحديثك للفئة القاعدية  فالتحديثات ستشمل كل الفئات الابناء 
بينما اذا استخدمت Interfases فانك ستكون مجبرا على اعادة تعريف الطرق الجديدة في كل الفئات الابناء.
انا ارى بنظري ان استخدام Abstract Classe هو انسب للتعامل مع كل الفئات ذات القرابة , اي ذات الارتباط ببعضها
بينما Interfaces تعتبر حل امثل للفئات غير المرتبطة.
لتتضح الفكرة اكثر دعني اضرب المثال التالي
لو فرضنا ان لدينا فئة الطائر و فئة الطائرة و كلا الفئتين يمتلكان الطريقة Flay  فانه من السخافة ان نقول ان الطائرة ترث من الطائر فقط لانها تمتلك خاصية الطيران , فانه من المناسب اكثر ان تكون هذه الطريقة موجودة في Interface
و كل فئة تستخدم الطريقة بما يناسبها 
اذا اردنا نقدم تعميما اكثر لحل هذه المشكلة هناك قول اخر هو لما لا يكون لدينا Abstract Classes يشمل على كل الوظائف ليساعدنا في التعديلات المستقبلية توفيرا للوقت اذ انني لن اضطر  لتعديل كل الفئات الاخرى التي تشتق من هذه الفئة (هل تذكر قولنا عن الفئات ذات القرابة و الارتباط) كما انها تسمح لنا باستخدام جزئيات فقط من الوظائف.
الخيار يتوقف عليك و على حسب حاجتك (لا تغفل الجزئية التي تحدث عنها الاخ الشاكي).
نستطيع الاعتماد على Interfaces و كذلك Abstract Classes و كذلك يمكن المزج بينهما.
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
#16
معلومة مفيدة اخي خضر ..

واضيف كذلك انه عند تعريف Abstract Class وClass عادية مشتقة من الـ Abstract بهذا الشكل:
PHP كود :
   //abstract
 
   abstract class Name
    
{

 
   }

 
   //normal class (inherts from Name)
 
   class Ahemd Name
    
{

 
   


لو عرفنا Instance من الAbstract class بواسطة طريقة الPointing (كما ذكر اخونا خضر في المشاركة السابقة) ،
PHP كود :
           Name n = new Ahemd(); 

ثم لو قمنا بالاستعلام عن الType بهذا الشكل
PHP كود :
           Name n = new Ahemd();
 
           MessageBox.Shown.GetType().Tostring() );//will return the concrete class (which is Ahmed) 

الـ Type المرجع سيكون Ahmed وليس Name ، ذلك بسبب ان الـ Interface والـ Abstract في حالة الPointing، كلاهما يقومان بإرجاع الـ Concrete type

وفي مثاالنا اعلاه الـ Concrete type هو Ahmed بسبب ان الـ Instance مشار اليه بواسطة متغير من نوع Abstract Smile

--

ومع ذلك ، عند استخدام المقارنة بالـ Type بواسطة المعامل Is  .. سنجد ان الرسالتين في الاسفل سيتم طباعتهما :

PHP كود :
           Name n = new Ahemd();

 
           if (n is Name)
 
           {
 
               MessageBox.Show("Hi"); //will be printed
 
           }
 
           if (n is Ahemd)
 
           {
 
               MessageBox.Show("Hi"); //will be printed
 
           


نعم ، المعامل Is  يرجع True سواء قارنت الـ object بالـ concrete class او بالـ Abtract class

طبعا نفس الموضوع بالضبط يحصل عند استخدام الانترفيس
الرد }}}
تم الشكر بواسطة: khodor1985 , ابو ليلى , sendbad100 , Amir_Alzubidy
#17
بما ان الموضوع انقلب الى نقاش تبادل خبرات ..
دعوني اعرض لكم احدى استخداماتي للـ Interface وايضا الـ Base Class


المشروع الذي اعمل عليه حاليا يحتوي على الكثير من الانظمة .. وهذا شيئ طبيعي لان المشروع عبارة عن لعبة ، ودائما الالعاب تحتوي على الكثير من الانظمة التي عليك مزامنتها مع الاحداث التي تحصل باللعبة

مثلا عند انفجار قنبلة في اللعبة ، الكثير من الانظمة يجب ان تعمل في وقت واحد ، منهم
Damage System
VisualEffect System
SoundEffect System
Score System


هنا نرى ان هذه الانظمة يجب ان تعمل في وقت واحد عند انفجار القنبلة ، وبالطبع يجب ان تتفاعل هذه الانظمة بشكل متزامن وصحيح بين بعضها البعض لذلك -في بعض الاحيان- تحتاج الى ارسال Message بينها ، وايضا تحتاج الى جهة او جهات تستقبل هذه الرسالة وتعالجها ..

لهذا الغرض ـ  نقوم بتعريف Interface لنستعمله لاحقا في التنصت على الرسائل ، ونقوم بتعريف Base Class لاستخدامها في تكوين الرسائل  (كما بالصورة)







اذن ، الانظمة التي بحاجة الى التنصت على الرسائل تقوم بوراثة الـ Interface ، كما هو الحال في الـ Damage System :





وفي احدى سكربتات اللعبة ، توجد الدالة التالية التي تتنفذ عند حصول اي انفجار في اللعبة ، يقوم هذا الكود بارسال رسالة الى جميع الانظمة التي تقوم بالتنصت (التي تشتق من الانترفيس IGameListener) :





وبالتالي ، جميع انظمة الصوت وانظمة المؤثرات البصرية وغيرها من الانظمة ستستلم هذه الرسالة وتقوم بالتفاعل مع الانفجار Smile



وان سالتني كيف شكل الدالة SendMessageToAll ، تفضل Smile



الدالة فقط من سطرين :Smile
ووظيفتها هي الدوران وجلب جميع الـ classes التي تشتق من الـ Interface المسمى IGameListener واستدعاء الدالة Listener  وتمرير الرسالة لها Smile




لماذا تم عمل IGameListiner كـ Interface ؟؟

لانها تحقق علاقة can-do مع الsystem
Damage System can Listen


بينما تم عمل MessageBase كـ Class بسبب ان العلاقة هي Is-A
BombMessage is a message



--


هذا كان احد الامثلة التطبيقية للـ Interface والوراثة
ايضا اذا كان عند الاخوان اي مثال تطبيقي اخر يمكنه المشاركة به لنستفيد Smile
الرد }}}


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [نقاش] نقاش حول تطبيق الفاتورة الإلكترونية فى السعودية المرحلة الثانية Zatca Integration AmrSobhy 2 1,599 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,017 16-12-17, 06:08 PM
آخر رد: sendbad100
  ZipFile Class Abu Ehab 1 2,265 18-11-16, 03:44 AM
آخر رد: abulayth
  [نقاش] الـ Delegate الشاكي لله 12 9,072 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,249 14-10-12, 03:05 PM
آخر رد: RaggiTech
  الفرق بين التعريف باستخدام overridde و new RaggiTech 0 2,861 14-10-12, 02:57 PM
آخر رد: RaggiTech

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


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