דריסת מתודות (בזמן ריצה)
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 29 מתוך 87.
בעוד שהעמסת מתודות מוכרעת בזמן ההידור, דריסת מתודות מדגימה פולימורפיזם בזמן ריצה. כאן, Java מחליטה איזו מתודה לבצע כשהתוכנית פועלת בפועל, על סמך הסוג בפועל של האובייקט ולא על סמך הסוג המוצהר של המשתנה.
למדת על דריסת מתודות בפרק הירושה. מה שהופך אותה לפולימורפית הוא האופן שבו Java מטפלת בה כאשר הפניה למחלקת אב מצביעה על אובייקט של מחלקת בת:
public class Animal {
public void speak() {
System.out.println("Some sound");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Bark!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}עכשיו נבחן מה קורה כשמשתמשים בהפניות מהסוג של מחלקת האב:
Animal myPet = new Dog();
myPet.speak(); // פלט: Bark!
myPet = new Cat();
myPet.speak(); // פלט: Meow!למרות ש־myPet מוכרז כ־Animal, Java מפעילה בזמן ריצה את המתודה שנדרסה בהתבסס על סוג האובייקט בפועל. זה נקרא שליחת מתודות דינמית. ה־JVM בוחנת מהו האובייקט בפועל, ולא מה שהמשתנה מציין.
כך מתאפשרים דפוסים רבי־עוצמה, כמו עיבוד אחיד של אובייקטים שונים:
Animal[] pets = {new Dog(), new Cat(), new Dog()};
for (Animal pet : pets) {
pet.speak(); // כל אחד קורא לגרסה משלו
}פולימורפיזם בזמן ריצה מאפשר לך לכתוב קוד גמיש שעובד עם טיפוסי אב, תוך שימוש אוטומטי בהתנהגות הנכונה של טיפוסי הבן.
אתגר
קלנבנה מערכת התראות שמדגימה פולימורפיזם בזמן ריצה בפעולה. תיצרו היררכיה של סוגי התראות, שבה אותה קריאה למתודה מפיקה פלטים שונים בהתאם לסוג האובייקט בפועל בזמן הריצה.
תארגנו את הקוד שלכם בארבעה קבצים:
Notification.java: צרו מחלקת בסיס שמשותפת לכל ההתראות. לכל התראה יש שדהrecipient(String). כללו בנאי לאתחול שלו, מתודת getter ומתודתsend()שמדפיסה:Sending notification to [recipient]EmailNotification.java: צרו מחלקה שמרחיבה את Notification. התראות דוא״ל מוסיפות שדהsubject. השתמשו ב-superלאתחול מחלקת האב. דרסו את המתודהsend()כדי להדפיס:Emailing [recipient]: [subject]SMSNotification.java: צרו מחלקה נוספת שמרחיבה את Notification. התראות SMS מוסיפות שדהphoneNumber. דרסו אתsend()כדי להדפיס:Texting [phoneNumber] for [recipient]Main.java: כאן הפולימורפיזם בזמן ריצה בא לידי ביטוי! תקבלו שלוש קלטים: שם נמען, נושא של הודעת דוא״ל ומספר טלפון. צרו מערך של הפניות מסוגNotificationהמכיל שלושה אובייקטים בסדר הזה: Notification בסיסי, EmailNotification ו-SMSNotification (כולם עם אותו נמען). לאחר מכן עברו בלולאה על המערך וקראו ל-send()בכל איבר. שימו לב איך Java קוראת אוטומטית לגרסה הנכונה שנדרסה, בהתאם לסוג האובייקט בפועל!
תקבלו שלוש קלטים: שם הנמען (String), נושא הודעת הדוא״ל (String) ומספר הטלפון (String).
הפלט שלכם צריך להציג שלוש שורות - כל קריאה ל-send() מפיקה פלט שונה, אף שאתם קוראים לאותה מתודה דרך הפניות מסוג Notification. כך פועלת שליחת מתודות דינמית!
נסו בעצמכם
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// קראו את הקלטים
String recipient = scanner.nextLine();
String subject = scanner.nextLine();
String phoneNumber = scanner.nextLine();
// TODO: צרו מערך של הפניות ל-Notification עם 3 איברים
// המערך צריך להכיל (בסדר הזה):
// 1. אובייקט בסיסי מסוג Notification
// 2. אובייקט מסוג EmailNotification
// 3. אובייקט מסוג SMSNotification
// כולם משתמשים באותו נמען
// TODO: עברו על המערך וקראו ל-send() עבור כל איבר
// כך מודגמת פולימורפיות בזמן ריצה!
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותשדות (מאפיינים)מתודת הבנאיהעמסת בנאיםחזרה – מחשבון פשוט4ירושה
ירושה בסיסית (extends)מילת המפתח superדריסת מתודות (@Override)שרשור בנאיםהמחלקה Objectירושה יחידה ורב־רמתיתלמה אין ירושה מרובה של מחלקותסיכום – היררכיית עובדים7מתודות מיוחדות ומחלקת Object
מתודת toString()equals() ו-hashCode()מתודת clone()compareTo() ו-Comparableהממשק Comparatorסיכום – מיון מותאם אישית2מצייני גישה ואנקפסולציה
סקירה של רמות הגישהמתודות Getter ו-Setterהסתרת מידעמילת המפתח finalסיכום – מנהל חשבון בנק5פולימורפיזם
יסודות העמסת מתודותדריסת מתודות (בזמן ריצה)המרה כלפי מעלה וכלפי מטההאופרטור instanceofמחלקות ומתודות מופשטותסיכום – מחשבון צורות8מושגי OOP מתקדמים
הרכבה מול ירושהאגרגציה מול הרכבהמחלקות פנימיות, מקוננות ואנונימיותEnums ומתודות של EnumRecords (Java 16+)מחלקות חתומות (Java 17+)3מאפייני מחלקה וחברים סטטיים
משתני מופע לעומת משתנים סטטייםמתודות סטטיותבלוקים סטטייםקבועים (static final)סיכום — מונה ומחלקת עזר6ממשקים ומחלקות מופשטות
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםמתודות ברירת מחדל וסטטיות בממשקמחלקות מופשטות לעומת ממשקיםממשקים פונקציונלייםסיכום – מערכת תשלומיםתרגלו בעצמכם: קומפיילר Java אונליין