بناء الفئات Classes فى الفجوال بيسك 6

استعرض الموضوع السابق استعرض الموضوع التالي اذهب الى الأسفل

بناء الفئات Classes فى الفجوال بيسك 6

مُساهمة من طرف السنى في الأحد يوليو 14, 2013 8:10 am

بناء الفئات Classes


الدرس عبارة عن جزء من الفصل الخامس من كتاب الأستاذ تركي العسيري "البرمجة كائنية التوجه OOP" الذي يشرح كيفية إنشاء الفئات  Classes. ويمكنكم الوصول لهذا الكتاب من هنا

  
سوف يتم تقسيم الدرس الى ثلاث اقسام رئيسية:



  • بناء الخصائص.
  •     
  • بناء الطرق.
  •     
  • بناء الأحداث .. القاء الأحداث.



الآن نبدأ مع شرح الأستاذ تركي العسيري:

بناء اول فئة مبسطة

والان شغل Visual Basic كي نبدأ بتصميم اول فئة تمثل شخص سنسميها CPerson . إختر الامر Add Class Module من قائمة Project ، ومن صندوق الحوار الذي –قد- يظهر امامك، اختر الرمز Class Module وانقر على الزر Open لتظهر لك نافذة اكواد تعريف الفئة، اضغط على المفتاح [ F4 ] لعرض نافذةخصائص الفئة، وعدل خاصية الاسم من Class1 الى CPerson ، واكتب هذا الكود في الفئة:

الرمز:


Public sName As String
Public dBirthDate As Date

وبهذا نكون قد انجزنا اول فئة بالاسم CPerson تحتوي على الخاصيتين sName وdBirthDate . تستطيع استخدام الفئة CPerson في أي مكان داخل مشروعك،اذهب الى الحدث Click التابع لنافذة النموذج واكتب هذا الكود:

الرمز:


Private Sub Form_Click()
Dim Turki As New cPerson
Dim Khaled As New cPerson
"تركي العسيري" = Turki.sName
Turki.dBirthDate = #1/1/1900#
"خالد الابراهيم" = Khaled.sName
Khaled.dBirthDate = #1/1/1979#
Print Turki.sName, Turki.dBirthDate
Print Khaled.sName, Khaled.dBirthDate
End Sub


قمنا -في الكود السابق – بانشاء كائنين Turki و Khaled من الفئة التي صممناها للتو CPerson ، ومن ثم قمنا بتعيين قيم للخاصيتين sName و dBirthDate  لكل كائن على حدة، وختمنا الكود بطباعة قيم الخصائص التابعة للكائنين Turki و .Khaled

صحيح ان الفئة السابقة لن تطبقها في حياتك البرمجية –بشكل جاد - لطباعة قيم متغيرات، الا ان الغرض الاساسي هو مجرد توضيح فكرة الفئات وطريقة استخدامها.

مصدر الدرس الاساسي


بناء الفئات

والان بعد ان عرفتك على الفكرة الاساسية من الفئات Classes سنبدأ بالتوغل في تفاصيل بناء خصائصها، طرقها واحداثها حتى تزيد من قوة الفئة.

بناء الخصائص
اذا عدنا الى مثال الفئة CPerson السابق، فسنلاحظ أن المبرمج يستطيع اسناد أي قيمة للخاصية dBirthDate ، وقد يعطي فرصة للمستخدم بادخال العمر من خانة نص:

الرمز:


Turki.iAge = CDate ( Text1.Text )


المشكلة في الكود السابق، ان المستخدم بامكانه ادخال أي عدد يمثل تاريخ ميلاد الشخص وقد يكون تاريخ لم يحل بعد، لذلك عليك التحقق من تاريخ الميلاد في كل مرة تمكن المستخدم من ادخال قيمة للخاصية :dBirthDate

الرمز:


If CDate( Text1.Text ) > Date Then
”خطأ في القيمة“ MsgBox
Else
Turki. dBirthDate= CDate(Text1.Text)
End If



يعيب الكود السابق انه يلزمك بعملية التحقق من القيمة في كل مرة تريد اسناد قيمة للخاصية dBirthDate ، والحل هو باستخدام نوع خاص من الاجراءات يسمى الخصائص والتي تمثل خصائص الكائن لتحميه من القيم الخاطئة:

الرمز:


Private m_dBirthDate As Date
Public Property Get dBirthDate () As Date
dBirthDate= m_dBirthDate
End Property
Public Property Let dBirthDate (ByVal dNewValue As Date)
If dNewValue > Date Then
”خطأ في القيمة“ MsgBox
m_dBirthDate = Date
Else
m_dBirthDate= dNewValue
End If
End Property



ملاحظة:  في الحقيقة، اظهار رسالة MsgBox من داخل الفئة – كما في الكود  السابق - يعتبر اسلوب غير احترافي وتصميم سيء جدا للفئات خاصة عندما تزيد احجامها، ويفضل ارسال رسالة خطأ بالطريقة Err.Raise  بدلا من MsgBox . الا انني استخدمت الدالة MsgBox في المثال لتقريب الفكرة اليك.

سيناريو تنفيذ الاجراءات السابقة سيكون كالتالي : في كل مرة تقوم بتعيين او  اسناد قيمة جديدة للخاصية dBirthDate ، سيتم استدعاء الاجراءLet dBirthDate وارسال القيمة الجديدة الى المتغير dNewValue ، وفي كل مرة تقوم بقراءة قيمة الخاصية dBirthDate ، سيتم استدعاء الاجراءGet dBirthDate والذي يعود بقيمة الخاصية. بامكانك ايضا اضافة خاصية جديدة iAge دون الحاجة لتعريف متغير خاص  Private لها:

الرمز:


Public Property Get iAge() As Integer
iAge = DateDiff("yyyy", m_dBirthDate, Date)
[color="#006400"]End Property[/color]


تلاحظ انني لم استخدم الا اجراء واحد وهو Get iAge وتجاهلت الاجراء  Let iAge وذلك لاني اريد ان اجعل الخاصية iAge للقراءة فقط Read Only ، فلو حاول المبرمج تعيين او كتابة قيمة جديدة للخاصية ستظهر رسالة خطأ :Read Only Property

الرمز:


ممكن جدا ‘ Print Turki.iAge
رسالة خطأ ‘ Turki.iAge = 80

وبامكانك تطبيق العكس، أي استخدام الاجراء Property Let دون الاجراء Property Get  لتجعل الخاصية للكتابة فقط  :Write Only Property

الرمز:


Private m_sPassword As String
Public Property Let sPassword ( sNewValue As String)
m_sPassword = sNewValue
End Property


المزيد ايضا، يمكنك التعامل مع اجراءات الخصائص كاجراءات Sub’s او Functions عادية لتمكنها من استقبال قيم :Parameters

الرمز:


Private m_sAddress (2) As String
Public Property Get sAddress( iIndex As Integer) As String
sAddress = m_sAddress ( iIndex )
End Property

Public Property Let sAddress(iIndex As Integer, sNewValue As String)
m_sAddress ( iIndex ) = sNewValue
End Property


وبامكانك استدعاء الخاصية sAddress بهذه الطريقة:

الرمز:


”حي الوهم – شارع الحقيقة“ = ( Turki.sAddress (0
”ولاية فلوريدا – باكستان“ = ( Turki.sAddress (1
”هاتف منزل 999 “ = ( Turki.sAddress (2


وعند الحديث عن الخصائص التي تمكنك من اسناد قيم لكائنات، فعليك استخدام الاجراء Property Set عوضا عن الاجراء :Property Let

الرمز:


Private m_PersonParent As CPerson
Public Property Get PersonParent( ) As CPerson
Set PersonParent = m_PersonParent
End Property

Public Property Set PersonParent( ByVal objNewValue As CPerson )
Set m_PersonParent = objNewValue
End Property


مواصفات الخصائص :Property Attributes

بامكانك تعديل مواصفات الخصائص عن طريق صندوق الحوار Procedure Attributes والذي تصل اليه من القائمة Tools بعد تحريك مؤشر الكتابة الى مكان اجراء الخاصية . من هذه المواصفات: جعل الخاصية افتراضية Default Propertey ، اخفاء الخاصية من نافذة مستعرض الكائنات Object Browser ، كتابة وصف للخاصية ....الخ، بامكانك استكشاف باقي الخيارات في صندوق الحوار، وعليك ان تعلم علم اليقين ان جميع هذه الخيارات ستحفظ في ملف الفئة CLS . فقط ولن تظهر لك في نافذة محرر ا كواد الفئة، فلو قمت بعملية نسخ ولصق اكواد الفئة الى فئة اخرى، عليك اعادة عملية تحرير مواصفات الفئة.



بناء الطرق

الطرق Methods ماهي الا اجراءات Sub’s او دوال Function معرفة داخل الفئة، ولا اعتقد انك بحاجة الى اعادة الفصل الثالث "لغة البرمجة BASIC " لتفاصيل بناء الاجراءات والدوال. مع ذلك، هذا مثال لطريقة تابعة للفئة :CPerson

الرمز:


Public Sub SetData(sName As String, dBirthDate As Date, sAddress As Variant)
Me.sName = sName
Me.dBirthDate = dBirthDate
Me.sAddress(0) = sAddress(0)
Me.sAddress(1) = sAddress(1)
Me.sAddress(2) = sAddress(2)
End Sub


بامكانك استدعاء هذه الطريقة بدلا من تعيين كل خاصية على حده:

الرمز:


بدلا من تعيين الخصائص ‘
Turki.sName = txtName.Text
Turki.dBirthDate = CDate ( txtBirthDate.Text )
Turki.sAddress (0) = txtAddress1.Text
Turki.sAddress (1) = txtAddress2.Text
Turki.sAddress (2) = txtAddress3.Text

استدعي الطريقة ‘
Turki.SetData txtName, CDate(txtBirthDate), Array(txtAddress1, _
txtAddress2, txtAddress3)




ملاحظة: حتى لو لم تقتع بفكرة تعيين الخصائص باستخدام الطرق كما في المثال السابق، تذكر ان استدعاء الطريقة السابقة اسرع بخمس مرات من تعيين قيمة كل خاصية على حده، وستؤثر هذه السرعة كلما كانت اكواد الكائن ابعد –كمكونات COM او .DCOM

بناء الاحداث

عندما نربط بين كلمتي الاحداث والفئات يتبادر لذهن مبرمجي VB4 حدث الانشاء  Class_Initialize  والانهاء Class_Terminates . لكن مع الاصدارات الاحدث، اصبحت الفئات قابلة على انشاء وتعريف احداث جديدة قابلة للتصريح من العملاء  Clientsالمستخدمين لتلك الفئة –والذين قد تكون انت احدهم.

الفكرة ليست صعبة او مختلفة عن الاحداث الموجودة في الادوات ، لن أخذ مثلا نافذة النموذج Form ، تم تعريف حدث فيها باسم Click ولاشتقاق واستخدام ذلك الحدث كل ما هو مطلوب منك وضع اسم الكائن ثم شرطة سفلية ومن ثم  اسم الحدث كما في هذا الكود:

الرمز:


Private Sub Form_Click()
اشتقاق حدث النقر من كائن النموذج ‘
End Sub

من هنا يتضح لنا ان الحدث بكل بساطة عبارة عن اجراء Sub قد يحتوي على متغيرات اضافية Parameters آالموجودة في حدث MouseDown او  .KeyPress الذي سنفعله هنا بالضبط هو تعريف حدث باسم DataHasBeenSent موجود في الفئة CPerson . ولتعريف هذا الحدث الجديد في الفئة سنستخدم الكلمة المحجوزة :Event

الرمز:


تعريف حدث جديد ‘
Event DataHasBeenSent(objTo As CPerson, bSuccess As Boolean)


لكن مهلا ! متى يستم تنفيذ هذا الحدث؟ هل سيكون ذلك عند استخدام خصائص وطرق الكائن كل مرة؟ ام عندما تزداد شهوة Visual Basic لتفجير الاحداث؟والجواب في أي وقت تريده عن طر يق استخدام العبارة RaiseEvent في داخل
الفئة. اكتب هذا الكود في الفئة :CPerson

الرمز:


Option Explicit
تعريف حدث جديد ‘
Event DataHasBeenSent(objTo As CPerson, bSuccess As Boolean)
تعريف طريقة جديدة في الفئة ‘
Public Sub SendData(objTo As CPerson)

هنا سنقوم بتفعيل الحدث ‘
If objTo Is Nothing Then
RaiseEvent DataHasBeenSent(objTo, False)
Else
RaiseEvent DataHasBeenSent(objTo, True)
End If
End Sub


والان ننتقل الى الجهة الاخرى ومعرفة كيفية التفاعل مع هذا الحدث كما تتفاعل  مع احداث الادوات الاخرى كـ Click وغيرها ، تتم العملية بنفس الطريقة التي تتعامل مع الادوات شريطة


  • استخدام الكلمة المحجوزة WithEvents مع تعريف الكائن.
  • لا يكون الكائن تابع لمصفوفة.
  • ان يتم الاعلان عن الكائن على مستوى الوحدة -أي .Public


سننشئ كائن باسم Caller من الفئة CPerson وسنحا ول الاستجابة لاحداث ذلك الكائن، في نافذة النموذج اكتب هذا الكود:

الرمز:


Option Explicit
Dim WithEvents Caller As CPerson
Private Sub Form_Click()
Dim Khaled As CPerson
Set Khaled = New CPerson
”خالد“ = Khaled.sName
Caller.SendData Khaled
End Sub

Private Sub Form_Load()
Set Caller = New MyClass
End Sub

Private Sub Caller_DataHasBeenSent(objTo As CPerson, bSuccess As Boolean)
If bSuccess Then
CPerson.sName "تم ارسال البيانات بنجاح الى: " MsgBox
Else
”لم اتمكن من ارسال البيانات“ MsgBox
End If
End Sub


ملاحظة : لا يوجد داعي لكتابة اسم الحدث الطويل بلوحة المفاتيح، فبمجرد تعريفك للسطر الذي توجد به كلمة WithEvents انتقل الى القائمة المنسدلة  Combo Box  في اعلى يسار نافذة التحرير حتى ترى اسم الكائن MyCaller مع باقي اسماء الادوات الموجود ة في النافذة.

مثال مبسط جدا يوضح طريقة الاستجابة للحدث Caller_DataHasBeenSent ، الذي يتم تفجيره بمجرد نجاح الطريقة .SendData


القاء الاحداث:

عن طريقة الكلمة المحجوزة WithEvents تستطيع تطبيق مبدأ القاء الاحداث Event Multicasting ، وهي عملية رمي الاحداث من كائن او اداة الى فئة كائن آخر بمجرد تفجير الحدث وقبل ان تنفيذ اكواده . سأوضح الفكرة بالمثال القديم الموجود في الفصل الثاني "النماذج والادوات " وبالتحديد عند فقرة "السيطرة على المدخلات" التابعة لفقرة "أداة النص TextBox "، تلاحظ ان الكود المستخدم للسيطرة على المدخلات كان طويل جدا، وقد اتفقنا –منذ البداية - انه من غير المعقول استخدام كل هذه الاكواد للتحقق من القيمة التي يكتبها المستخدم في خانة النص، ولكن هنا سنستخدم الكود مرة واحدة فقط، وسنضعه في فئة باسم :CNumTextBox


الرمز:


الاداة التي ستلقي احداثها الينا ‘
Public WithEvents TextControl As TextBox
اكواد تمنع المستخدم من كتابة إلا الارقام ‘
Private OldText As String
Private OldSelStart As Long

Private Sub TextControl_GotFocus()
عندما يكون التركيز على الاداة ‘
لابد من حفظ قيمتها ‘
OldText = TextControl.Text
OldSelStart = TextControl.SelStart
End Sub

Private Sub TextControl_Change()
متغير يمنع استدعاء الاجراء تراجعيا ‘
Static bExitNow As Boolean
If bExitNow Then Exit Sub
If Not IsNumeric(TextControl.Text) Then
المفتاح المدخل ليس رقم ‘
قم باعادة عرض القيمة القديمة ‘
bExitNow = True
TextControl.Text = OldText
bExitNow = False
TextControl.SelStart = OldSelStart
Else
القيمة المدخلة رقمية اذا ‘
قم بحفظها ‘
OldText = TextControl.Text
OldSelStart = TextControl.SelStart
End If
End Sub

Private Sub TextControl_KeyDown(KeyCode As Integer, Shift As Integer)
OldSelStart = TextControl.SelStart
End Sub

Private Sub TextControl_KeyUp(KeyCode As Integer, Shift As Integer)
OldSelStart = TextControl.SelStart
End Sub

Private Sub TextControl_MouseUp(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
OldSelStart = TextControl.SelStart
End Sub

Private Sub TextControl_Click()
OldSelStart = TextControl.SelStart
End Sub


والان في كل مرة تريد انشاء اداة نص TextBox جديدة لا تقبل إلا الاعداد، فلا يوجد داعي لكتابة كل الاكواد السابقة، وانما قم بالقاء جميع احداث اداة النص الى الفئة:

الرمز:


Dim NumText As New CNumTextBox
Dim NumText2 As New CNumTextBox

Private Sub Form_Load()
Text1 = “0”
Text2 = “0”
Set NumText.TextControl = Text1
Set NumText2.TextControl = Text2
End Sub


تمكنا ببساطة شديدة في الكود السابق من جعل الاداتين Text1 و Text2 لا تقبلان إلا اعداد بفضل القاء الاحداث .Event Multicastin


الى هنا انتهى شرح الأستاذ تركي العسيري بالنسبة لكيفية إنشاء الفئات.أرجوا ان يكون الكل فهم الدرس وتعم الفائدة للجميع.

السنى
.......
.......

تاريخ التسجيل : 18/02/2011
المساهمات : 186
النقاط : 346
التقيم : 18
الجنس : ذكر

الرجوع الى أعلى الصفحة اذهب الى الأسفل

استعرض الموضوع السابق استعرض الموضوع التالي الرجوع الى أعلى الصفحة


 
صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى