סדר קריאות בנאים
אחת השאלות הנפוצות ביותר (וגם מקור להרבה טעויות במבחנים) היא: כאשר אנחנו יוצרים אובייקט ממחלקה יורשת, איזה בנאי מופעל קודם - של האב או של הבן?
האינטואיציה: בסיס (Base) והרחבה (Extends)
כדי להבין את הסדר, נסתכל על המילים שבהן Java משתמשת. מחלקת האב נקראת לרוב מחלקת בסיס (Base Class). מחלקת הבן נוצרת באמצעות המילה השמורה extends (מרחיבה).
חשבו על בניית בית: אי אפשר לבנות את הקומה השנייה (ההרחבה) לפני שיצקנו את היסודות והקומה הראשונה (הבסיס). כדי שמחלקה תוכל ליצור אובייקט שהוא הרחבה של מחלקת הבסיס - היא חייבת שיהיה לה מה להרחיב!
מכאן נובע חוק ברזל: הבנאי של מחלקת האב תמיד יסיים את עבודתו לפני הבנאי של הבן.
חתימות שונות: ניתוק מוחלט בין האב לבן
טעות נפוצה היא לחשוב שאם יצרנו אובייקט של הבן עם בנאי שמקבל פרמטר אחד, הוא חייב להפעיל בנאי של האב שמקבל פרמטר אחד. זה ממש לא נכון!
הבנאי שיופעל במחלקת האב תלוי אך ורק במה שכתבנו מפורשות בתוך פקודת ה-super(...) בשורה הראשונה של בנאי הבן. מחלקת הבן יכולה לקבל רשימת פרמטרים שונה לחלוטין מזו שהיא מעבירה לאב.
public class Vehicle {
public Vehicle(String brand, int wheels) {
System.out.println("Vehicle Created: " + brand + " with " + wheels + " wheels.");
}
}
// המחלקה המרחיבה (Extends)
public class ElectricCar extends Vehicle {
// בנאי הבן מקבל רק פרמטר *אחד*!
public ElectricCar(String brand) {
// אבל הוא מפעיל בנאי של האב שדורש *שני* פרמטרים (מעביר 4 גלגלים קבוע)
super(brand, 4);
System.out.println("Electric System Initialized.");
}
}
בדוגמה זו, ברגע שנעשה new ElectricCar("Tesla"), בנאי הבן יקבל פרמטר בודד, אבל מיד יקרא ל-super("Tesla", 4). הבסיס ייווצר קודם עם 4 גלגלים, ורק אז תסתיים בניית הרכב החשמלי.
סגירת פינות: איך הריצה מתבצעת בפועל?
זמן קריאה מול זמן סיום
חשוב לדייק: ה-new קורא קודם כל לבנאי של הבן. הבנאי של הבן מתחיל לרוץ, אבל בגלל שפקודת ה-super() חייבת להיות השורה הראשונה, הוא מיד עוצר, עובר להריץ את הבנאי של האב עד הסוף, ורק אז הבן מסיים את שאר הקוד שלו.
מה קורה כשאין super?
אם שכחנו לכתוב super() בשורה הראשונה בבנאי של הבן, הקומפיילר לא מוותר. הוא שותל שם בסתר קריאה ל-super(); (הבנאי הריק של מחלקת הבסיס). אם למחלקת הבסיס אין בנאי ריק (כי הגדרנו בנאי אחר ולא יצרנו אחד ריק מפורשות) - נקבל שגיאת קומפילציה!