Virtual VS. Abstract

אבי דקל

New member
Virtual VS. Abstract

אם הבנתי נכון, המטרה של Virtual הוא לאפשר פולימורפיזם, והמטרה של אבסטרקט הוא לאפשר מחלקות שאי אפשר לממש אותם, רק לרשת מהם. 1. האם נכון ?
2. אם הגדרתי במחלקה X מתודה מסויימת כ virtual, זה אומר שאני חייב גם לממש אותה ב X עצמו, או שזה לא חובה ? 3. אם אני יורש מ X, ורוצה להעניק פונקציונליות אחרת למתודה שהוגדרה ב X כ virtual, אני עושה זאת ע"י המילה override לפני שם המתודה במחלקה היורשת ? 4. אם Y יורש מ X ולא מממש בעצמו את המתודה הוירטואלית שהוגדרה ב X, ואובייקט מסוג Y מפעיל מתודה בשם הזה, האם המתודה שהוגדרה ב X תופעל ? 5. אם הגדרתי ב X מתודה רגילה (לא וירטואלית), ו Y יורש מ X ואני רוצה לשנות את התפקוד של המתודה הנ"ל, אני אוכל לעשות זאת, למרות שהיא לא הוגדרה כוירטואלית ? 6. מה משמעות ה new לפני הגדרת מתודה ? (שבירת שרשרת ירושה ? מה זה אומר ?) 4. מתודות אבסטרקטיות יכולות להיות מוגדרות אך ורק במחלקה אבסטרקטית, ובמחלקה אבסטרקטית יכולים להיות מוגדרים אך ורק מתודות אבסטרקטיות. אמת ? תודה !!!
 

gilad g

New member
../images/Emo26.gif

1. כן
2. חובה. אבל ה"מימוש" יכול להיות ריק:
public virtual void Func() { }​
3. יאפ
4. כן
5. כן, ע"י שימוש ב-new:
public void new Func(...)​
6. ראה תשובה לשאלה 5 + הרחבה: תראה מה קורה כשמתשמשים ב-virtual/override:
public class A { public virtual void Print() { Console.WriteLine("A"); } } public class B : A { public override void Print() { Console.WriteLine("B"); } } //.... B b = new B(); b.Print(); //Will print "B", of course. A a = (A)b; //we are casting b back to A. a.Print(); //Will print "B"!
עכשיו שים לב מה קורה כשמשתמשים ב-new:
public class A { public void Print() { Console.WriteLine("A"); } } public class B : A { public new void Print() { Console.WriteLine("B"); } } //.... B b = new B(); b.Print(); //Will print "B", of course. A a = (A)b; //we are casting b back to A. a.Print(); //Will print "A", and not "B"!
הבנת?
7. המשפט השני אינו נכון. במחלקות אבסטרקטיות אין חובה להגדיר רק מתודות אבסטרקטיות. אחרת, מה יהיה ההבדל בינן לבין Interface-ים?
 

אבי דקל

New member
../images/Emo47.gif המון תודה + המשך...

4. בתנאי שהמתודה הוירטואלית הוגדרה ב X, אינה Private, לא ? במידה והיא Private, אז תתקבל שגיאת קומפילציה ? 5. הכוונה היא שנניח הגדרתי במחלקה X, מתודה print רגילה (לא וירטואלית), וכעת Y יורש מ X, ואני רוצה שהמתודה print בדיוק תבצע משהו אחר. ע"י new במקרה הזה, אוכל לכתוב את print מחדש (כלומר, שתבצע פעולה אחרת ?) 6. זה בילבל אותי
בדוגמא הראשונה, אתה מציב למשתנה a את המשתנה b שעובר Casting למשתנה מסוג המחלקה A, כלומר - יהיה ניתן להתייחס אליו כאילו הוא A, ואם אני מתייחס אליו כאילו הוא A (בשל ההמרה), אז הפעלה ה Print אמור להפעיל את ה PRINT של A.... כיצד הוא הגיע ל PRINT של B ? הוא בכלל לא אמור להכיר את המשתנה הזה בטיפוס B, מכיוון שהוא עבר הסבה...
 

gilad g

New member
תשובות ../images/Emo26.gif

4. לא יודע אם תתקבל שגיאת קומפילציה, אבל אין משמעות למתודה וירטואלית פרטית. 5. כן. 6. זוהי בדיוק המשמעות של פולימורפיזם. הוא יבצע את B, ולא את A, בגלל שב-A המתודה Print מסומנת ב-virtual
 
תוספת קטנה

הוא מבצע את B לא רק בגלל ה-virtual אלא גם בזכות ה-override. נראה שאתה מעולם של ++c, אם כן, חשוב על ה-v-table ואיך היא נראית בכל אחד מהמצבים.
 

אבי דקל

New member
אני מתכוון כאן :

public class A { public virtual void Print() { Console.WriteLine("A"); } } public class B : A { public override void Print() { Console.WriteLine("B"); } } //.... B b = new B(); b.Print(); //Will print "B", of course. A a = (A)b; //we are casting b back to A. a.Print(); //Will print "B"!​
אתה מגדיר משתנה מסוג A, מציב אליו משתנה מסוג B שמוסב ל A - מדוע שיתייחס אליו כאילו הוא B ?!
 

gilad g

New member
כי

כשהוא בא להריץ את print, הוא בדק ומצא שהיא virtual, ואז הוא מחפש האם האובייקט הזה הוא בעצם אובייקט שיורש מ-A, ולא A בעצמו. אז הוא מצא שזה בעצם אובייקט B (עשינו new B ולא new A, נכון?
), ובגלל הפולימורפיזם הוא מריץ את B.Print ולא את A.Print.
 

אבי דקל

New member
../images/Emo41.gif../images/Emo41.gif../images/Emo41.gif../images/Emo41.gif../images/Emo41.gif../images/Emo41.gif../images/Emo41.gif../images/Emo41.gifחמור מאוד..

המשמעות היא שאצטרך הסבר מעט רחב יותר על פולימורפיזם. בעקרון אני יודע שהמטרה שלו היא היכולת להתייחס שאובייקטים שונים, באותה דרך. למשל, אם אני הייתי כותב מנוע של דפדפן, היתה לי לולאה שרצה על מערך כל האובייקטים שאמורים להופיע על המסך, ופשוט הייתי מפעיל לכולם את המתודה Draw (או Render), גם בלי לדעת איזה על אובייקט בדיוק אני כרגע נמצא, אבל אני יודע בוודאות שיש לו את המתודה הנ"ל, ומה שהיא עושה זה לצייר את האובייקט על המסך. אני מבין את זה בתאוריה, אבל כשאני רואה את זה כעת בדוגמא שלך בפרקטיקה, כנראה שזה פחות מובן
גיגלתי קצת, אבל המאמרים באנגלית סיבכו אותי עוד יותר. אודה מאוד למי שיוכל לכתוב בצורה מעט רחבה יותר על מימוש הפולימורפיזם, כיצד עושים, כיצד זה עובד ולמה בעצם זה עובד ככה... תודדדדדדדדה !
 
למעלה