בניית מודאלים גנאריים
-
התוכנית שאני בונה בנוייה באופן הבא:
Imports System.Collections.ObjectModel Public Class GenaricTable(Of TRecord) ' הטבלה הגנארית ' יש בה כל מיני פונקציות ומאפיינים ' מחזיקה אוסף של רשומות מטיפוס מסויים Public WithEvents MainCollection As ObservableCollection(Of TRecord) Public Property Sum '.... End Class Public Class Connection ' יצירת קשרי גומלין בין שני טבלאות גנאריות Public Sub New(GenaricTableOut As Object, GenaricTableIn As Object) ' כאן אני צריך להפעיל כל מיני פונקציות של הטבלאות הגנאריות ' למשל Dim X = GenaricTableUot.Sum Dim Y = GenaricTableUot.MainCollection ' זה עובד, אבל דבר כזה יכול להביא לשגיאה '... End Sub End Class Public Class Person ' מחלקה בשביל רשומה בטבלה '... End Class Public Class Order ' מחלקה בשביל רשומה בטבלה '... End Class Class MainWindow Private GTPerson As New GenaricTable(Of Person) Private GTOrder As New GenaricTable(Of Order) Public Sub New() Dim C As New Connection(GTPerson, GTOrder) End Sub End Class
הבעיה שלי עם המחלקה Connection שאני צריך להעביר אליה שני טיפוסים של שני הטבלאות ואיך עושים זאת? כי כמו שזה כתוב כעת אם אובג'קט יכול להביא לשגיאות כי אנו עלולים לטעות ולהכניס למשתנה משתנה מטיפוס שלא התכוונו אליו והקומפיילר לא יתריע על כך, אלא נקבל את השגיאה רק בזמן ריצה ב- casting הלא חוקי. וגם אם שם של הפונקציה Sum ישתנה תיוצר שגיאה כי ה Rename לא יתפוס את הפונקציה שדבוקה לאובג'קט.
תודה רבה לכולם ושבת שלום.
נ.ב
מזל טוב לרגל הנושא ה 100 בפורום שלנו !פורסם במקור בפורום CODE613 ב26/12/2013 22:43 (+02:00)
-
אני מאוד לא מבין את הכיוון ואת הדרך, לא הבנתי גם למה במקום באובגקט אתה לא משתמש עם המחלקה היפה שעשית (GenaricTable).
כלומר המחלקה קונקשיין לפי איך שהתחלת אמורה להיראות ככה:Public Class Connection(Of TRcordA, TRecordB) Public Sub New(GenaricTableOut As GenaricTable(Of TRcordA), GenaricTableIn As GenaricTable(Of TRecordB)) End Sub End Class
אבל אני מריח את הבעיה עליה אתה שואל.
אתה מנסה להתמודד מראש עם מחלקות שונות שיתנו פחות או יותר אותה פונקציונליות אבל עדיין מחלקות שונות.
אגב, בC#, אין אופציה בכלל למה שעשית. אם אתה לא יודע מראש את סוג המחלקה, אין לך שום אפשרות להשתמש במאפיין/מתודה שאת הבטוח שיהיה בה).
אז מה עושים? אז פה כדאי מאוד לסקור חזק את נושא ה"תכנות מונחה עצמים"', OOP בלועזית מרשימה.בOOP יש שתי דברים שמאוד נוגעים לשאלתך:
א. Interface - ממשק (מנשק לפי האקדמיה :)) שזה עצם שמכיל רשימה של חוקים, שכל מחלקה שמכריזה על עצמה כמממשת את אותו Interface, חייבת לממש.
ב. מחלקת אב אבסטרקטית (מופשטת). בהנחה שאתה מכיר את המושג "ירושה", אז אפשר ליצור מחלקה למחצה (שאין לה שום טעם משל עצמה, וגם אי אפשר ליצור ממנה מופע), ותפקידה זה לתרום את הפונקציונליות שלה למחלקות היורשות ממנה.
שתי הדרכים נראים דומות אך יש הרבה הבדלים בינהם, הן באופן השימוש והן במטרתו.
במקרה שלך כדאי לך ליצור אב טיפוס, או ממשק או מחלקה מופשטת, ולוותר על השימוש בגנריות ולהשתמש בטיפוס מוגדר, מסוג אב.
באופן כללי ניתן לומר כלל שהשימוש בגנריות מומלץ א. מתי שלא פונים הרבה לאלמנטים בתוך האובייקט ב. מתי שמתכוננים לתת שירות גם לטיפוסים שלא תחת אחריותינו כלל.פורסם במקור בפורום CODE613 ב29/12/2013 11:53 (+02:00)
-
תודה רבה,
את נושא הירושה והממשקים אני מכיר ואני משתמש למשל בממשק כזה:Imports System.ComponentModel Public Interface IRecord Inherits INotifyPropertyChanged Property ID As Integer Sub OnPropertyChanged(ByVal name As String) End Interface Public Class GenaricTable(Of TRecord As IRecord) ' הטבלה הגנארית ' יש בה כל מיני פונקציות ומאפיינים ' מחזיקה אוסף של רשומות מטיפוס מסויים Public WithEvents MainCollection As ObservableCollection(Of TRecord) Public WithEvents ConnectionsCollection As ObservableCollection(Of Connection) Public Property Sum '.... End Class
@דוד ל.ט.
אני מאוד לא מבין את הכיוון ואת הדרך, לא הבנתי גם למה במקום באובגקט אתה לא משתמש עם המחלקה היפה שעשית (GenaricTable).
כלומר המחלקה קונקשיין לפי איך שהתחלת אמורה להיראות ככה:רציתי באמת לעשות כמו שאתה מציע אבל אז נתקעתי עם השורה הבאה בתוך GenaricTable, שורה זו שכחתי להביא בהודעה הראשונה:
Public WithEvents ConnectionsCollection As ObservableCollection(Of Connection)
כלומר חייב להיות בכל טבלה אוסף של קשרי גומלין כאשר כל קשר גומלין מכיל טבלה אחת מסוג שונה מאשר הטבלה שמכילה את אוסף הקשרי גומלין. בין כל קשרי הגומלין של טבלה מסויימת יכולים להיום כמה וכמה טיפוסים שונים לגמרי.
מה הארכיטקסטרה הנכונה בכל המבנה הזה?פורסם במקור בפורום CODE613 ב29/12/2013 12:58 (+02:00)
-
או: תעשה כמו שהצעתי וקונקשיין תחליף לObject.
או: כדי להשתמש בקונקשנים בלי קאסט צור ממשק לקונקשיין ככה:
Public Class GenaricTable(Of TRecord As IRecord) Public WithEvents ConnectionsCollection As ObservableCollection(Of IConnection) End Class Public Class Connection(Of TRecordA As IRecord, TRecordB As IRecord) Implements IConnection Public Sub New(GenaricTableOut As GenaricTable(Of TRecordA), GenaricTableIn As GenaricTable(Of TRecordB)) End Sub End Class
או: אתה יכול להחליט לעשות גם ככה:
Public Class GenaricTable(Of TRecord As IRecord) Implements ITable Public WithEvents ConnectionsCollection As ObservableCollection(Of Connection) End Class Public Class Connection Public Sub New(GenaricTableOut As ITable, GenaricTableIn As ITable) End Sub End Class
פורסם במקור בפורום CODE613 ב29/12/2013 15:08 (+02:00)
-
תודה,
עשיתי ממשק גם ITable וגם IConnection
הכל עבד מצויין חוץ ממאפיין אחד ב Connection שלא התאים ל ממשק:'במחלקה: Public Class Connection(Of TRecordA As IRecord, TRecordB As IRecord) Implements IConnection Public Property MainCollectionOfTableOut As ObservableCollection(Of TRecordA) _ Implements IConnection.MainCollectionOfTableOut End Class 'בממשק: Property MainCollectionOfTableOut As ObservableCollection(Of IRecord)
למה זה קורה? על פי סדר הממשקים זה היה אמור להתאים, ומה אפשר לעשות אם לא שוב שימוש באובג'קט?
אם אני מבין נכון אז אע''פ שאת TRecordA אפשר להסב [=קאסט] ל IRecord
אבל (Collection(Of TRecordA אי אפשר להסב ל (Collection(Of IRecord אולי שייך לעשות כאן העמסת אופרטור של הקאסט ?פורסם במקור בפורום CODE613 ב29/12/2013 17:19 (+02:00)
-
Public Class Connection(Of TRecordA As IRecord, TRecordB As IRecord) Implements IConnection(Of TRecordA, TRecordB) Public Property MainCollectionOfTableOut As ObservableCollection(Of TRecordA) Implements IConnection(Of TRecordA, TRecordB).MainCollectionOfTableOut Public Property MainCollectionOfTableIn As ObservableCollection(Of TRecordB) Implements IConnection(Of TRecordA, TRecordB).MainCollectionOfTableIn End Class Public Interface IConnection(Of TRecordA As IRecord, TRecordB As IRecord) Property MainCollectionOfTableOut As ObservableCollection(Of TRecordA) Property MainCollectionOfTableIn As ObservableCollection(Of TRecordB) End Interface
פורסם במקור בפורום CODE613 ב29/12/2013 17:52 (+02:00)
-
צודק. זה תלוי בך, אתה לא חייב לתפוש את החבל מכל הכיוונים. לא היית חייב לכתוב באינטרפייס את הפרופרטיז הללו, וגם להישאר עם הגנריות שלהם.
אני הייתי עושה הכל עם אינטרפייס ולפחות את האוספים, ככה:Public Class Connection Implements IConnection Public Property MainCollectionOfTableIn As ObservableCollection(Of IRecord) Implements IConnection.MainCollectionOfTableIn Public Property MainCollectionOfTableOut As ObservableCollection(Of IRecord) Implements IConnection.MainCollectionOfTableOut End Class Public Interface IConnection Property MainCollectionOfTableOut As ObservableCollection(Of IRecord) Property MainCollectionOfTableIn As ObservableCollection(Of IRecord) End Interface
פורסם במקור בפורום CODE613 ב29/12/2013 18:46 (+02:00)
-
תשמע, אני ממשיך לעבוד על פיתוח המסד נתונים והממשקים האלו זה ממש כלי נפלא ביותר, אתה יכול לגשת לכל טיפוס לא משנה מה הוא יהיה ויש לי איתו שפה משותפת בזכות הממשק המשותף שיש לו עם אחרים, אתה יכול להכניס למערך שלל של טיפוס שונים העיקר שכולם תחת אותו ממשק ועם כולם אתה יכול לעבוד בלא אובג'קט ממש תענוג.
אין כמו OOPפורסם במקור בפורום CODE613 ב01/01/2014 21:09 (+02:00)