MiniMizer פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 היי, קיבלתי מטלה בנושא פולימורפיזם בשיעורי הבית ואני מתלבט ביישום של אחת הפונקציות הנדרשות.בקצרה, הסיפור הוא כזה:יש מפעל שמייצר כלי מטבח (כוסות, צלחות, מזלגות וכו') ומכונה שממיינת את כל המוצרים. בתחילת כל יום מזינים למכונה את המוצרים שהמפעל מתכוון לייצר באותו יום (האובייקטים האלו מאוחסנים בוקטור) ולאחר מכן המכונה צריכה לבדוק כל מוצר שמגיע אליה ולהחליט האם הוא תקין - היא עושה זאת על ידי השוואתו לאובייקטים שנמצאים בוקטור שהזכרתי מקודם.יצויין גם כי כל הכלים במפעל יורשים מאובייקט משותף בשם Dish.הפרמטר הראשון והחשוב ביותר בהשוואה הוא לבדוק האם הם בכלל מאותו טיפוס (כלומר אם הגיע למכונה מזלג, והמפעל אמור לייצר היום רק צלחות, המוצר הזה אמור לעוף ישר לקופסא של מוצרים פגומים, שזה גם וקטור חסר חשיבות כלשהו).עכשיו, אני מכיר שתי דרכים לעשות את זה:א) להוסיף לאבא שדה של שם (סטרינג פשוט) שיאותחל על ידי כל אחד מהבנים באופן שונה. עבור כל אובייקט שיגיע למכונה, לעשות השוואה של השדה הזה מול כל אחד מהאובייקטים בוקטור.ב) לממש אופרטור השוואה בכל אחד מהבנים על ידי שימוש ב-dynamic_cast מתאים.הבעיה היא שהאפשרות הראשונה נחשבת על ידי סגל הקורס כ"התחכמות" וייתכן שיורידו על זה נקודות (למה להשתמש בפתרון הלוגי הפשוט ביותר אם אפשר לסבך הכל?) והאפשרות השניה דורשת הרצת dynamic_cast על כל תא בוקטור - ואם בשלב כלשהו יהיו לי הרבה מאוד תאים, זה לא הפתרון המועדף בשפת המעטה.יש דרכים נוספות בהן אפשר להשוות בין טיפוסים בזמן ריצה? :-\ קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 שתי הדרכים קצת הורסות את כל הקטע של פולימורפיזם. זו שאלה די טיפשית.הפתרון הפשוט ביותר הוא בדיוק פתרון א' שהצעת (רק שהייתי משתמש ב-Enum ולא במחרוזת). למעשה, אם אין הבדל "התנהגותי" בין המוצרים השונים, בכלל הייתי זורק לפח את הרעיון של ירושה ופשוט מממש את הכל במחלקה אחת (עם שדה שקובע את סוג המוצר). קישור לתוכן שתף באתרים אחרים More sharing options...
MiniMizer פורסם 2009 ביוני 16 מחבר Share פורסם 2009 ביוני 16 אתה כזה חמוד כשאתה נאיבי ;D לצערי יש כל מני מגבלות על התרגיל :-\ב-enum אני לא יכול להשתמש כי זה הורס עוד יותר את הגנריות של הקוד (שכבר ככה די נהרסת אם אני מכניס בעצמי סטרינג של שם לכל בן) - יכול להיות שבעתיד יהיו עוד 50 מוצרים שונים שמישהו אחר יממש ויותר פשוט לדרוש ממנו להוסיף סטרינג של שם לקונסטרקטור מאשר להסתבך עם enum שלא תהיה לו גישה אליו בכלל.ולצערי אי אפשר לזנוח את רעיון הירושה בגלל מגבלות התרגיל.. לכל כלי יש פרמטרים שונים במקצת (לצלחות וכוסות יש רדיוס וגובה, למזלגות יש אורך)... ברור שאפשר לממש את הכל במחלקה אחת, אבל אני חייב ליצור לפחות שלוש מחלקות שיורשות מהאב הראשי (ועוד מעין מחלקת ביניים). קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 אז אין באמת דרך אחרת.גם בשפות אחרות (ג'אווה, #C) משתמשים בבדיקה של טיפוסים בזמן ריצה. קישור לתוכן שתף באתרים אחרים More sharing options...
MiniMizer פורסם 2009 ביוני 16 מחבר Share פורסם 2009 ביוני 16 איך עושים את זה בשפות אחרות? אין איזו פונקציה פשוטה שיכולה לעשות את זה? :\ קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 בג'אווה וב-#C פשוט יש keywords מתאימים לזה (instanceof ו-is).ב-++C יש לך שתי אפשרויות:http://en.wikipedia.org/wiki/Run-time_type_informationhttp://en.wikipedia.org/wiki/Typeid קישור לתוכן שתף באתרים אחרים More sharing options...
MiniMizer פורסם 2009 ביוני 16 מחבר Share פורסם 2009 ביוני 16 אז אני יכול בעצם להשתמש ב-typeid, לא?חוץ מזה שלא ממש הבנתי מה היא מחזירה.. קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 אובייקט מטיפוס type_info.הפתרון הזה דווקא נראה לי פחות טוב, כי אי אפשר לבדוק אם הטיפוס של האובייקט שלך יורש מטיפוס אחר (אפשר רק להשוות).אגב, יש דרך קצת יותר יפה לעשות את פתרון א':להגדיר ל-Dish פונקציה וירטואלית טהורה בשם getType שמחזירה String. כל אחד מסוגי המוצרים השונים יממש את getType בהתאם. קישור לתוכן שתף באתרים אחרים More sharing options...
MiniMizer פורסם 2009 ביוני 16 מחבר Share פורסם 2009 ביוני 16 אגב, יש דרך קצת יותר יפה לעשות את פתרון א': להגדיר ל-Dish פונקציה וירטואלית טהורה בשם getType שמחזירה String. כל אחד מסוגי המוצרים השונים יממש את getType בהתאם. עוד מישהו הציע לי את זה, נראה לי שזה באמת הפתרון שאני אלך עליו. תודה רבה! קישור לתוכן שתף באתרים אחרים More sharing options...
ktbnus פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 אובייקט מטיפוס type_info.הפתרון הזה דווקא נראה לי פחות טוב, כי אי אפשר לבדוק אם הטיפוס של האובייקט שלך יורש מטיפוס אחר (אפשר רק להשוות).אגב, יש דרך קצת יותר יפה לעשות את פתרון א':להגדיר ל-Dish פונקציה וירטואלית טהורה בשם getType שמחזירה String. כל אחד מסוגי המוצרים השונים יממש את getType בהתאם.סתם מתוך סקרנות, איך הפתרון הזה יותר טוב? זה פחות או יותר מה שהאופרטור typeid עושה. ואיך הוא בדיוק פותר לך את הבעייה? קישור לתוכן שתף באתרים אחרים More sharing options...
Component פורסם 2009 ביוני 16 Share פורסם 2009 ביוני 16 אני גם בעד פתרון הסטרינג, אבל אם אתה רוצה משהו אחר תוכל לעשות double dispatchhttp://en.wikipedia.org/wiki/Double_dispatch קישור לתוכן שתף באתרים אחרים More sharing options...
roma4k פורסם 2009 ביוני 18 Share פורסם 2009 ביוני 18 ואם רוצים בכל זאת לעשות עם ה DYNAMIC CAST איך אני יכול לבדוק איבר בוקטור אם הוא מאותו טיפוס של האיבר שאותו אני רוצה לבדוק?כאמור, אסור לציין את הטיפוס הנידרש בתוך הקוד של המכונה הבודקת, זאת אומרת אני לא יכול לרשום בקוד המכונה בדיקה בסגנון הבא: TYPE* dynamic_cast<TYPE*> (object);אם האיבר מתאים אני אמור להכניס אותו למקום המתאים בוקטור שמכילים איברים מהסוג שלו ולכן חשבתי לעבור בלולאה על האיברים בוקטורים וברגע שיש התאמה בין האיבר הניבדק לבין האיבר בוקטור, אז להכניס אותו לאותו המקום. קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2009 ביוני 18 Share פורסם 2009 ביוני 18 כמו שאמרנו כאן, יש לך שתי אפשרויות:הראשונה היא להוסיף פריט מזהה לקלאס שלך (כמו פונקציית getType).השנייה היא להשתמש בבדיקת טיפוסים בזמן ריצה.את הדרך השנייה אפשר לממש באמצעות dynamic_cast או באמצעות typeid.אגב, אם אתה לא רוצה להשתמש ב-typeid אתה יכול לעשות משהו כזה:class Dish { virtual bool isSameType(Dish*) = 0;}ואז בכל קלאס שמממש את Dish לעשות משהו כזה:class Plate : public Dish { virtual bool isSameType(Dish* d) { Plate* p = dynamic_cast<Plate*>(d); return (p != null); }}כמובן שאת המימוש הזה תצטרך לעשות לכל טיפוס שיורש מ-Dish. אופציה קצת יותר חסכונית היא לשלב ירושה ו-Templates.יש גם את האופציה של double dispatch שהוצעה מעליי, אבל אני לא בטוח שהיא ישימה במקרה הזה (ואם כן, אז זה פתרון מאוד מסורבל). קישור לתוכן שתף באתרים אחרים More sharing options...
roma4k פורסם 2009 ביוני 18 Share פורסם 2009 ביוני 18 ואז אני יכול למעשה לעשות לולאה כזאת?for ( BoxIterator iterator = m_dishBoxes.begin(); iterator != m_dishBoxes.end(); iterator++ ) { if ( iterator->isSameType( dish ) ) { iterator->pushback(dish); break; } } תודה על ההסבר. קישור לתוכן שתף באתרים אחרים More sharing options...
שניצל פורסם 2009 ביוני 18 Share פורסם 2009 ביוני 18 מה הטיפוס של m_dishBoxes? אם זה וקטור של וקטורים, אז אתה לא יכול, כי לוקטור אין פונקציה בשם isSameType. קישור לתוכן שתף באתרים אחרים More sharing options...
Recommended Posts
ארכיון
דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.