تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
الدرس التاسع عشر : ال Encapsulation
#1
منقول من المنتدى القديم
كاتب المقال احمد جمال المشرف العام
بسم الله الرحمن الرحيم .
السلام عليكم ورحمة الله وبركاته .

يهدف مبدأ ال Encapsulation والذي سبق شرحه باختصار في الدرس السابع عشر إلى اخفاء التفاصيل الداخلية لأي كلاس عن اعين باقي المبرمجين ، باختصار شديد لنفترض نظام محاسبي يتضمن نظام لادارة المخازن ، وآخر للصيانة ، وثالث من اجل المبيعات .

في هذه الحالة يدعوك مبدأ ال Encapsulation ليكون لكل واحد من هذه النظم عدد محدد من الدوال للدخول والخروج من هذا النظام والتي يمكن للنظم الثلاثة التواصل من خلالها ، فمثلاً في نظكام المبيعات تجد (اضافة عملية مبيعات) ( اضافة مشتريات ) ( خصم ) ... الخ في مجموعة محدودة جداً من الدوال .

طبعاً لو لاحظت ان عملية مثل اضافة عملية مبيعات تتطلب طابوراً من الأوامر ، يتضمن فتح قاعدة البيانات والتأكد من ان البيانات المدخلة صحيحة والتأكد من وجود الكمية ومن ثم تخزين الناتج في قاعدة البيانات ، تم تجميعها في النهاية على شكل أمر واحد يقوم زميلك الآخر الذي يقوم ببرمجة واجهات المستخدم إلى استخدامه بدلاً من الغوص في كل هذه التفاصيل الفنية .

كما لاحظت ، يفيد هذا الموضوع الأشخاص التي تعمل في مجموعات اولاً ، حيث لن اكون مضطراً لفهم كودك بالكامل ويكفيني ان اعرف كيف اتعامل معك ، كما ان الكود سيكون مصمماً على شكل هرم حيث كل أمر يستتبعه مجموعة من الأوامر ، لكن سيكون زميلك المبرمج قادراً فقط للوصول إلى رأس الهرم وهو ما يقلل كثيراً من الأخطاء ، كما يحمي متغيراتك الخاصة من العبث بها عن طريق الخطأ من المبرمجين الآخرين .

هذا المفهوم الذي تحاول ان توصله لك كل لغات برمجة OOP ، ولتطبيق هذا المفهوم هناك العديد من النقاط التي سنتطرق لها في هذا الدرس .
الرد }}}
تم الشكر بواسطة:
#2
منقول من المنتدى القديم
كاتب المقال احمد جمال المشرف العام
قبل ان نواصل درسنا هذا ، اول نقطة لا بد ان تضعها في ذهنك انك مبرمج وهناك مبرمج آخر هو المستخدم ... بمعنى مثلاً انك تقوم ببرمجة كلاس ويقوم زميلك المبرمج باستخدام هذا الكلاس كجزء من المشروع .

استخدام دوال public للوصول إلى متغيرات private .

لنفترض المثال التالي بخصوص ال Person الذي قمنا بانشاءه عدة مرات على مستوى الدروس السابقة :

C#:
كود :
class Person
{
public int Age;
}
VB.net:
كود :
Class Person


    Public Age As Integer

End Class

ولإن زميلك العزيز في الفريق الخاص بادخال بعض البيانات بشر - وجل من لا يسهو - قام بكتابة الجملة التالية :

C#:
كود :
Person Ahmed = new Person();
Ahmed.Age = 999999999999;

VB.net:
كود :
Dim Ahmed As New Person()
Ahmed.Age = 999999999999
ولو ان السهو في رقم بهذا الحجم يعد شبه مستحيل ، لكننا قد نتعرض لهذه المشكلة في اشياء اقرب للواقع ، وابسط من ذلك لو انه يقوم بقراءة القيمة من المستخدم ليرسلها لك مباشرة ، وفي وجود مستخدم - غلس - فإن مثل هذه المدخلات تعد أمراً طبيعياً .

طبعاً هذا المدخل سيسبب الدمار العاجل للكلاس الذي قمت بعمله ، كما ان زميلك مبرمج شاشات الادخال ربما لن يكلف نفسه عناء برمجة امر التحقق من الادخال ، لذا تأتي النصيحة الدائمة ، امنع متغيراتك من الظهور لمستخدمها - المبرمج الآخر - وضع بدلاً منها دوال لقراءتها او الكتابة إليها بالشكل التالي :

C#:
كود :
class person
{
private int Age;
public string SetAge(int x)
{
if(x>100 || x<1)
  return "you can't edit age like that";

Age=x;
return "done";

}
public int GetAge()
{
return Age;
}
}

VB.net:
كود :
Class person
    Private Age As Integer

    Public Function SetAge(ByVal x As Integer) As String
        If x > 100 OrElse x < 1 Then
            Return "you can't edit age like that"
        End If

        Age = x
        Return "done"

    End Function

    Public Function GetAge() As Integer
        Return Age
    End Function
End Class

طبعاً تسمية المتغيرات باسم x هو خطا كما اتفقنا سابقاً ، دالة Set ينبغي ان تأخذ الشكل التالي مثلاً :

C#:
كود :
public string SetAge(int Age)
{
if(Age>100 || Age<1)
  return "you can't edit age like that";

this.Age=Age;
return "done";

}

VB.net :
كود :
Public Function SetAge(ByVal Age As Integer) As String
    If Age > 100 OrElse Age < 1 Then
        Return "you can't edit age like that"
    End If

    Me.Age = Age
    Return "done"

End Function

وذلك حسبما تعلمنا من خصائص this أو Me في الدرس السابق ...

ربما يبدو لك الأمر مملاً او طويلاً ، لكنه مثل هذه الأمور في المشاريع الجدية تعد نقاطاً حيوية لا يمكن الاستغناء عنها لإنها قد تتسبب في سقوط للمشروع يكلف عدة ملايين بسبب خطأ بسيط .

تنبيه أخير ، الدالة GetAge يطلق عليها اسم Accessor أما الدالة SetAge فتسمى باسم Mutator .
الرد }}}
تم الشكر بواسطة:
#3
كاتب المقال احمد جمال المشرف العام
ارسال القيم كجزء من ال Constructor :

طريقة أخرى يمكنك استخدامها كبديل او مع الطريقة السابقة ، وهي اتاحة الفرصة للمستخدم لتمرير بارميترات قيم المتغيرات ضمن المشيد Constructor ، في الكلاسات الكبيرة سيكون لزاماً عليك استخدام الطريقة الأولى إلى جانب هذه الطريقة حيث انك لن تتصور المستخدم يقوم بتمرير قيم كل المتغيرات لحظة انشاء Object من ال Class .

مثال هذه الطريقة :

C#:
كود :
class Person
{
private int Age;
public Person(int Age)
{
if(Age>100 || Age<1)
  return "you can't edit age like that";

this.Age=Age;
return "done";
}
}

VB.net:

كود :
Class Person
    
    Private Age As Integer
    
    Public Sub New(ByVal Age As Integer)
        
        If Age > 100 OrElse Age < 1 Then
            Return "you can't edit age like that"
        End If
        
        Me.Age = Age
        Return "done"
    End Sub
الرد }}}
تم الشكر بواسطة:
#4
كاتب المقال احمد جمال المشرف العام
استخدام ال Type Property :

بنفس الطريقة السابقة ، ولكن بطريقة اخرى واعتماداً على تحويل المتغير إلى خاصية لكل منها دالتان : Set و Get ، يتم كتابة ذلك بالشكل التالي :

C#:
كود :
class Person
{
public int Age
{
get { return Age;}
set
{
if (!(value>100 || value<1))
Age=value;
}
}
}

VB.net:

كود :
public Property Age() As Integer
      Get
          Return Age
      End Get
      Set
          If Not (value > 100 OrElse value < 1) Then
              Age = value

          End If
      End Set
  End Property
End Class


والآن يمكنك الوصول المباشر إلى Age ، ولكن قبل تطبيق اي شيء سيتم استدعاء Set ، وفي حالة طلب شيء سيتم الحصول عليه من Get ، وهو ما يتيح لك التأكد من بيانات الادخال او عمل بعض العمليات على عمليات الاخراج .

لعلك لاحظت ايضاً أن Set و Get هما public لان الخاصية (وليس المتغير في هذه الحالة) المسماه Age هي public ، ولكن منذ .net 2.0 اصبح بامكانك التعديل في معرف الوصول الخاص ب Set او Get على حدة ، بالشكل التالي مثلاً :

C#:

كود :
public int Age
كود :
{
get { return Age; }
protected set { Age = value; }
}

VB.net:

كود :
Public Property Age() As Integer

كود :
Get
      Return Age
  End Get
  Protected Set
      Age = value
  End Set
End Property

إذا كنت ترغب في عمل Read Only Property فيمكنك ازالة الخاصية Set ، أما لو اردت العكس لعمل Write Only Property فأزل الخاصية Get ، هذا المثال ل Read Only Property :

C#:
كود :
public int Age
{
get { return Age; }
}

VB.net:

كود :
Public ReadOnly Property Age() As Integer
    Get
        Return Age
    End Get
End Property
الرد }}}
تم الشكر بواسطة:
#5
ردود مهمة
النبهاني
مبرمج محترف من الدرجة الأولى
جهد جميل بارك الله فيك

لكن اتمنى منك مراجعة الكود التالي :
كود :
Class Person
    
    Private Age As Integer
    
    Public Sub New(ByVal Age As Integer)
        
        If Age > 100 OrElse Age < 1 Then
            Return "you can't edit age like that"
        End If
        
        Me.Age = Age
        Return "done"
    End Sub
End Class

كتابة شيء بعد Return يعني انها Function وليست Sub وهذا شيء

------------
احمد جمال رد
صحيح ، اصلاً وجود return غير مناسب .

شكراً على التنبيه .
الرد }}}
تم الشكر بواسطة:



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


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