الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ال Generics في الفيجوال بيسك 2005

مغلق
بدأه Ayoub JAMAL EL IDRISSI في 23 فبراير 2006 · 5 رد · 1,745 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

Generics

المكتبة BCL(Base Class Library) تحتوي منذ الآن على فضاء اسماء جديد و هو System.Collections.Generic و يحتي هذا الفضاء(اذا صح التعبير) على عدة كلاسات تمكنك من انشاء مجموعات نوعيه (Generic Collections) . و يقال نوعية Generic لأنه عند التعريف أنت تقوم بتحديد مساحة محددة للكائنات التي تريد و لا تقوم بتحديد نوع.

ان ال Generics تمكننا من كسب وقت كبير في عملنا و انت لو كنت قد قمت من قبل بانشاء Collections خاصة بك عن طريق الكود فلن تتجاهل الوقت و الجهد الكبيرين في انشاءها . لكن الآن و مع الفيجوال بيسك 2005 يمكنك عن طريق ال Generics انشاء Collections خاصة بك في سطر واحد لا أكثر.لم يعد ضروريا الآن ان تنشأ Collection لكل نوع فما عليك الآن سوى استعمال هذه الامكانية الجديدة و تحدد النوع الذي تريد انشاء Collection له.

الآن دعونا من الكلام النظري الذي أظن انه غير مفهوم للكثيرين و لننتقل الى سرد أمثلة تطبيقية حتى نتمكن من فهم هذه التقنية الجديدة. لنفرض أن لدينا مثلا Class اسمه Customer يحتوي على خاصيتين (في المثال وضعناهم على شكل متغيرات فقط من أجل الاختصار) :

Public Class Customer

    Public Name As String

    Public CreditLimit As Decimal



    Public Sub New(ByVal CustomerName As String, _

      ByVal CustCreditLimit As Decimal)

        Name = CustomerName

        CreditLimit = CustCreditLimit

    End Sub

End Class

و الآن عندما أنشأنا كلاس مثل هذا يمكننا انشاء لائحة زبائن بكل سهولة و عن طريق السطر التالي :

Dim Customers As New System.Collections.Generic.List(Of Customer)

استطعنا الآن و بكل سسهولة انشاء لائحة من المستخدمين و التي تحتوي فقط على نوع Customer و تستطيع عن طريق تقنية ال IntelliSense من الوصول الى كائنات ال Customer التي تحتويها هذه اللائحة التي أسميناها Customers. و بامكانك عمل نفس الأمر كانشاء Collections من انواع اخرى كال Product... الآن تستطيع كتابة كود كالتالي :

Dim custA As New Customer("CustA", 1000)

Customers.Add(custA)

    Dim custB As New Customer("CustB", 2000)

Customers.Add(custB)

For Each c As Customer In Customers

    MessageBox.Show("Customer: " & c.Name & _

      ", limit: " & c.CreditLimit)

Next

كما تلاحظ ففي السطر الأول قمنا بانشاء زبون جديد و أعطيناه اسم و CreditLimit عن طريق ال Constructor ثم بعد ذلك أضفناه الى لائحة الزبائن التي أنشأناها مسبقا و ذلك عن طريق الmethod المسماة Add و بعد ذلك أنشانا زبون جديد و أضفناه الى اللائحة ثم انتقلنا الى عمل حلقة تكرارية حيث أننا نمر على كل عنصر من عناصر اللائحة Customers و اذا كان العنصر من نوع Customer يعني زبون نقوم باظهار اسمه و رصيده. لكن دعنا نرى الآن الكود أسفله :

'compile error: Product cannot be converted to Customer

Dim prodA As New Product("ProdA", CDec(29.95))

Customers.Add(prodA)

كما ترى فقد أنشأنا عنصر جديد لكنه ليس Customer بل Product و أضفناه الى اللائحة Customers لكن هنا سيحدث خطأ لأننا حددنا عندما عرفنا اللائحة انها ستقبل فقط الزبائن Customer فاذا أضفنا عنصر من نوع مخالف سيعطينا الخطأ المكتوب باللون الأخضر.

طبعا ستجد عدة انواع أخرى متفرعة من فضاء الأسماء System.Collections.Generic مثال ذلك Dictionary(of K,V) و LinkedList(of T) و Stack(of T).

يمكنك ان تنشأ Generic خاص بك يتوافق مع احتياجاتك بمساعدة التعريف الجديد Of. لنفرض أن لدينا الكلاس المسمى Comparer و الذي يمكننا من مقارنة عدة عناصر :

Public Class Comparer(Of itemType)

        '...

End Class

يمكنك ايضا ان تضع الزام و تحديد نوع الكلاس الذي يمكن قبوله من طرف هذا الكلاس عند انشاء نسخة جديدة منه و مثال على ذلك :

Public Class Comparer(Of itemType As IComparable)

        '...

End Class

طبعا هنا حددنا و قلنا للكلاس Comparer الا يقبل سوى الكلاسات التي تقوم بعمل Implements لل Interface المسماة IComparable و طبعا يمكنك عمل عدة تحديدات من أجل ان تتفادى أخذاء غير متوقعة.

الآن دعونا نوسع الكلاس Customer الذي رأيناه سابقا و نقوم بعمل Implements للواجهة IComparable

Public Class Customer

    Implements IComparable

    Public Name As String

    Public CreditLimit As Decimal



    Public Sub New(ByVal CustomerName As String, _

      ByVal CustCreditLimit As Decimal)

        Name = CustomerName

        CreditLimit = CustCreditLimit

    End Sub



    Public Function CompareTo(ByVal obj As Object) As Integer _

      Implements IComparable.CompareTo

        Dim c As Customer = CType(obj, Customer)

        If CreditLimit > c.CreditLimit Then Return 1

        If CreditLimit < c.CreditLimit Then Return -1

        Return 0

    End Function

End Class

كما ترون عملنا Implements للواجهة IComparable و اضيفت لنا ال Function المساة CompareTo و اظن ان الكود جد واضح لكن دعني أشرحه قليلا حتى تكون الامور واضحة جدا. هذه ال Function تقوم بمقارنة العنصر الحالي يعني الكلاس الحالي مع كلاس او عنصر آخر ممرر لها Obj فاذا كان العنصر الحالي أكبر من العنصر الممرر اليها ترجع 1 اما اذا كان أصغر فترجع -1 لكن اذا كانا متساويين فالقيمة المرجعة تكون 0، في السطر الأول من ال Function قمنا بانشاء كائن Customer و أعطيناه قيمة العنصر الممرر الذي نوعه هنا Object و لكي يتلائم مع النوع Cutomer قمنا باستعمال الكلمة المفتاحية CType و بعد ذلك نقوم بالمقارنة.

الآن نقوم بانشاء كلاس Product مثلا و نقوم فيه بمقارنة الأثمنة (Price) و الكود المختصر هو التالي :

Public Class Product

    Implements IComparable

    Public Name As String

    Public Price As Decimal



    Public Sub New(...)...

    Public Function CompareTo(...)...

End Class

الآن لنرى الكلاس Comparer الذي انشأناه و نرى كيف يقوم بعمل المقارنة بين الأنواع او المقارنة النوعية (generic compare)

Public Class Comparer(Of itemType As IComparable)



    Public Function GetLargest(ByVal Item1 As itemType, _

    ByVal Item2 As itemType) As itemType

        Dim i As Integer = Item1.CompareTo(Item2)

        If i > 0 Then Return Item1

        If i < 0 Then Return Item2

        Return Nothing

    End Function

End Class

كما ترى اضفنا Function جديدة الى الكلاس و أسميناها GetLargest و هي تستقبل عنصرين طبعا من نفس النوع هنا و تقوم بارجاع العنصر الأكبر، في السطر الأول قمنا باعلان متغير i من نوع Integer و يأخذ القيمة المرجعة من التعبير :

Item1.CompareTo(Item2)

طبعا هذا السطر جد واضح فنحن نقوم بمقارنة العنصر Item1 بالعنصر Item2 و نحتفظ بالقيمة المرجعة في المتغير i.

بعد ذلك نقوم بفحص قيمة المتغير i فاذا كان أكبر من 0 اذا فالعنصر Item1 هو العنصر الأكبر فتقوم الدالة بارجاعه اما اذا كانت قيمة المتغير أصغر من 0 اذا فالعكس صحيح و نرجع ال Item2 اما في حالة ما اذا كان المتغير i يساوي 0 اذا فالعنصرين متساويين و عندها لا نرجع شيئا (Return Nothing).

الآن يمكننا العمل بهذا الكلاس بطريقة بسيطة و سهلة و هذا الكود يوضح الكيفية :

Dim pc As New Comparer(Of Product)

Dim prod1 As New Product("LittleOne", 10)

Dim prod2 As New Product("BigOne", 100)

Dim lp As Product = pc.GetLargest(prod1, prod2)

MessageBox.Show("The more expensive product is: " & lp.Name)



Dim cc As New Comparer(Of Customer)

Dim cust1 As New Customer("SmallCo", 1000)

Dim cust2 As New Customer("LargeCo", 5000)

Dim lc As Customer = cc.GetLargest(cust1, cust2)

MessageBox.Show("The customer with a higher limit is: " & lc.Name)

كما تلاحظون هنا قمنا باستعمال نفس الكلاس Comparer فمررنا في الأول نوع Product و في الثاني نوع Customer و بدون ال Generics كان يلزمنا ان ننشأ لكل نوع كلاس خاص مثلا ProductComparer و CustomerComprarer.

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

اتمنى ان يكون هذا المقال قد نال رضاكم و يمكنكم قراءة المزيد من المقالات في هذا المجال عبر زيارتكم هذا الموقع

و السلام عليكم

تم تعديل هذه المشاركة بواسطة crazy-man في 23 فبراير 2006 في 03:06

#3

ملاحظات:

1- أتمنى أن تجد مثالا أفضل من Comparer لأن عندك في الأصل IComparable! مثالك في الأعلى صنع فئة تعمل نفس عمل فئة أخرى!

2- طريقة كتابة compareTo في الفئة Customer ليست جيدة، إذ بما أنك تستخدم Generics،، لماذا تستخدم CType؟! إلا إذا كانت الفئة IComparable ليست Generic وهذه مأساة!

يعني قصدي: يجب أن يكون توقيع الأمر هكذا أساسا:

public Function CompareTo(c as Customer)

بدلا من Object!

3- من الأمور الأساسية في البرمجة الغرضية، أن تجعل مكونات الفئات Private وليس Public! انظر إلى Customer وإلى Product.. كل من Name و القيم الأخرى وضعتها Public وهذا لا ينبغي أبدا! ولست بصدد ذكر العيوب الكثيرة لهذه الطريقة! ولاسيما أن ليس موضوع النقاش!

متمنيا لك مقالات ممتازة دوما!

بالتوفيق!

تم تعديل هذه المشاركة بواسطة أبومازن في 23 فبراير 2006 في 16:29

#4

بارك الله فيك أخي العزيز ابو مازن و انت عودتنا دائما ردودك البناءة و الموجهة لنا

حقيقة بالنسبة للملاحظة الأولى فهذا ليس سوى مثال و أنا لست بصدد انشاء فئة جديدة لكن أردت فقط تقريب الفكرة الى القراء فاذا فهموا الغرض و كيفية عمل ال Generics عند اذ يمكنهم انشاء ما يريدون.

اما بالنسبة للملاحظة الثانية فعندما تعمل Implements للواجهة IComprable يتم وضع ال Function الموضحة و هي CompareTo ببارامتر من نوع Object و قد فكرت فعلا بتغييرها الى نوع الصنف Custumor لكن خفت أن يشكل هذا سوء فهم حيث ان اي واحد سيعمل Implements IComprabale سيتم وضع ال Function الموضحة بدلا من تلك التي تأخذ بارامتر ك Custumor و هذا كل ما في الأمر

اما ملاحظتك الأخيرة فقد ذكرت أن استعمال القيم ك Public تم فقط للإختصار يعني بدل عمل Propreties قمت بعمل متغيرات Public و انا لست أريد كما لا تريد أنت أيضا ان أتطرق الى موضوع آخر و هو كيفية التعامل مع البيانات في ال OOP لأنه موضوع لوحده

و انا أنتظر كل ملاحظاتكم و السلام عليكم و رحمة الله و بركاته

#5
اقتباس
اما بالنسبة للملاحظة الثانية فعندما تعمل Implements للواجهة IComprable يتم وضع ال Function الموضحة و هي CompareTo ببارامتر من نوع Object و قد فكرت فعلا بتغييرها الى نوع الصنف Custumor لكن خفت أن يشكل هذا سوء فهم حيث ان اي واحد سيعمل Implements IComprabale سيتم وضع ال Function الموضحة بدلا من تلك التي تأخذ بارامتر ك Custumor و هذا كل ما في الأمر

تقصد أن بيئة التطوير ستكتب هذه الجملة عنك... فهمت عليك..

لكن سؤال: هل تستطيع فعلا تغييرها إلى Customer؟ حاول وأخبرني .... فأنا أعتقد أن المترجم سيخرج أخطاء ولن يقبل التغيير، إلا إذا كانت Generic و IComparable ليست Generic وهذا غريب بعض الشيء! إذ من الأولى أن تكون IComparable مجنسة، لكنها ليست كذلك! بحثت في دليل MS لكن لم أجد IComparable مجنسة!

تم تعديل هذه المشاركة بواسطة أبومازن في 23 فبراير 2006 في 21:15

#6

انا لم أجربها لكن لكن أظن ايضا انها لن تتغير كون ال IComparable عبارة عن Interface لذا فلا يمكن تغيير ال Parametrs الخاصة بال Functions الخاصة به

هذا الموضوع مغلق.

مواضيع مشابهة