المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : الدرس التاسع عشر : ال Encapsulation دورة .net 2008


khaledbelal
02-20-2010, 03:07 PM
بسم الله الرحمن الرحيم .
السلام عليكم ورحمة الله وبركاته .

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

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

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

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

هذا المفهوم الذي تحاول ان توصله لك كل لغات برمجة OOP ، ولتطبيق هذا المفهوم هناك العديد من النقاط التي سنتطرق لها في هذا الدرس .

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

استخدام دوال 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 .

ارسال القيم كجزء من ال 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

استخدام ال Type Property :

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

C#:

class Person
{
public int Age
{
get { return Age;}
set
{
if (!(value>100 || value<1))
Age=value;
}
}
}


VB.net:


Class Person
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