תכנות מונחה עצמים (OOP) - פולימורפיזם - המתודה הוירטואלית

סגור באמצעות טופס זה תוכלו לספר ולהמליץ לחבריכם..
שם השולח:
כתובת דוא"ל של השולח:
שם המקבל:
שלח לכתובת דוא"ל:
הוסף הערה:

 (Virtual methods) מתודות וירטואליות
 
 
 
מתודה וירטואלית (Virtual Method) הנה מתודה אשר מוגדרת וממומשת במחלקת הבסיס, אולם ניתן לספק לה מימושים נוספים בכל אחת מהמחלקות הנגזרות.
נהוג לומר, שהמחלקה הנגזרת יכולה לדרוס/לרמוס  (Override) את המימוש הקיים במחלקת הבסיס.
כאשר נפעיל מתודה וירטואלית יופעל המימוש המתאים לטיפוס האובייקט המוקצה ולא לייחוס, במילים אחרות, המימוש יופעל על פי האובייקט המוקצה דינאמית ולא על פי הייחוס המחזיק בכתובת ההקצאה.
 
הגדרת מתודה וירטואלית מתבצעת באמצעות המילה השמורה virtual, הגדרת מימוש נוסף במחלקה הנגזרת מחייבת שימוש המילה השמורה override.
 
מתודה וירטואלית אינה יכולה להיות static וכמובן שאינה יכולה להיות private (תסבירו למה?), אבל יכולה להיות Protceted.


תחביר:
 1  : class Base 
 2  : { 
 3  :      . . . 
 4  :     public virtual void Func() 
 5  :     { 
 6  :         . . . 
 7  :     } 
 8  : } 
 9  : class Derived : Base 
 10 : { 
 11 :     . . . 
 12 :     public override void Func() 
 13 :     { 
 14 :         . . . 
 15 :     } 
 16 : } 
 17 : class program 
 18 : { 
 19 :     public static void Main() 
 20 :     { 
 21 :         Base b = new Derived(); 
 22 :         b.Func(); 
 23 :     } 
 24 : } 
שורה 1: הגדרת מחלקת הבסיס.
שורה 4: הגדרת המתודה הוירטואלית באמצעות המילה השמורה virtual מתבצעת תמיד במחלקת הבסיס.
שורה 9: הגדרת המחלקה הנגזרת.
שורה 12: המחלקה הנגזרת דורסת (Override) את המימוש הקיים במחלקת הבסיס.
שורה 21: ייחוס מטיפוס הבסיס Base מקבל מיוחס לאובייקט מהמחלקה הנגזרת Derived.
שורה 22: איזה מימוש יופעל? זה של המחלקה הנגזרת.



דוגמת קוד (Virtual Method):
מחלקת הבסיס - Base.

 1  : class Person 
 2  : { 
 3  :     private string firstName; 
 4  :     private string lastName; 
 5  :     public Person(string fn, string ln) 
 6  :     { 
 7  :         this.firstName = fn; 
 8  :         this.lastName = ln; 
 9  :     } 
 10 :     public virtual void Print() 
 11 :     { 
 12 :         Console.WriteLine("Name={0} {1}", lastName, firstName); 
 13 :     } 
 14 : } 
שורה 10: הגדרת מתודה וירטואלית במחלקת הבסיס.

המחלקה הנגזרת - Derived:

 1  : class Employee : Person 
 2  : { 
 3  :     private float salPerHour; 
 4  :     private float workingHours; 
 5  :     public Employee(string fn, string ln, float sal, float hours) : 
 6  :         base(fn, ln) 
 7  :     { 
 8  :         salPerHour = sal; 
 9  :         workingHours = hours; 
 10 :     } 
 11 :     public override void Print() 
 12 :     { 
 13 :         base.Print(); 
 14 :         Console.WriteLine("Salary = {0}", salPerHour * workingHours); 
 15 :     } 
 16 : } 
שורה 11: דריסת המתודה הוירטואלית Print אשר הוגדרה בבסיס.

Main:

 1  : class Program 
 2  : { 
 3  :     static void Main(string[] args) 
 4  :     { 
 5  :         Person p1 = new Person("Foigel", "Dutch"); 
 6  :         p1.Print(); 
 7  :  
 8  :         Person p2 = new Employee("Foigel", "Dutch", 34, 170); 
 9  :         p2.Print(); 
 10 :     } 
 11 : } 
שורה 5:  ייחוס מטיפוס בסיס שמקבל כתובת של אובייקט ממחלקת הבסיס.
שורה 6:  תופעל המתודה של מחלקת הבסיס.


שורה 8:  ייחוס מטיפוס בסיס שמקבל כתובת של אובייקט מהמחלקה הנגזרת.
שורה 9:  יופעל המימוש המוגדר במחלקה הנגזרת.

במחלקה Person מוגדרת המתודה Print כוירטואלית, המשמעות היא שבכל אחת מהמחלקות הנגזרות, אשר ירשו את המחלקה Person, ניתן לדרוס את המתודה ולספק מימוש אחר.
אם נרצה נוכל להגדיר זאת כאינטרפרטציה שמחלקה מספקת להתנהגות המוגדרת במחלקת הבסיסית.
המחלקה Employee דורסת את המימוש של המתודה Print אשר הוגדרה כוירטואלית במחלקה הבסיסית Person, המחלקה Employee למעשה מספקת מימוש נוסף למתודה וירטואלית זו.
 


פלט:
פלט תוכנית הדוגמה VirtualMethod01

כפי שניתן להבחין מהפלט של התוכנית, בקריאה השניה ל-()Print  הופעל המימוש השייך למחלקה הנגזרת.
הייחוס p מטיפוס הבסיס עדיין מכיר רק את חברי המחלקה אשר הוגדרו במחלקת הבסיס, ולכן הוא קורא למתודה ()Print המוגדרת במחלקת הבסיס, אולם הפעם יופעל המימוש אשר הוגדר במחלקה Employee.
דהיינו, ניתן לומר שבתוכנית הדוגמה קיימת מתודה אחת ויחידה בשם Print , מתודה זו מוגדרת במחלקת הבסיס Person, המחלקה Employee רק מספקת מימוש נוסף לאותה מתודה של Person , מימוש אשר יופעל כאשר האובייקט המוקצה הנו מ- Employee .
המימוש אשר יופעל בפועל נקבע בזמן ריצה מכיוון שרק בסמוך להפעלת המתודה הוירטואלית ניתן לדעת באיזה אובייקט מדובר (Late Binding).

כללים במימוש מתודות וירטואליות 
  • החתימה של המתודה הוירטואלית המוגדרת במחלקת הבסיס חייבת להיות זהה בכל (שם המתודה, פרמטרים, ערך מוחזר, הרשאת גישה) לחתימה של המימושים הנוספים שלה במחלקה הנגזרת.
  • ניתן להמשיך ולספק למתודה וירטואלית אשר מוגדרת במחלקת הבסיס מימושים נוספים בשאר המחלקות הנגזרות.
  • לא ניתן להגדיר מתודות static כוירטואליות. virtual מתייחס להתנהגות של אובייקטים ומחלקות.
  • לא ניתן להגדיר מתודות private כוירטואליות, משום שלא ניתן יהיה לממשם במחלקה הנגזרת. 
  • לא ניתן להגדיר בצורה מפורשת override כ- virtual למרות שהיא וירטואלית.
 



כל הזכויות שמורות למחבר ©