מכל מלמדי השכלתי

מכל מלמדי השכלתי – הקוד הבא נכתב ע”י סטודנט שלי, שבא אלי בהפסקה כדי שאעזור לו למצוא את הבאג. אני מודה שלקח לי המון זמן לגלות את זה, זה אחד הקשים (למרות שאחרי שמוצאים אותו זה טריוויאלי…). אז מי יודע מדוע ולמה הקוד הבא אינו עובר קומפילציה?

public class A {

    public A(int x)

    {

        System.out.println(x + “”);

    }

}

public class B extends A {

    public void B(int x)

    {

        super(x);

    }

}

פתרון

מסתבר שג’אווה מאפשרת להגדיר שיטות שהשם שלהן הוא כמו שם הבנאי. כלומר, במחלקה B  בעצם אין בנאי, כיוון שהמילה void בחתימת השיטה הופכת אותו לשיטה ולא לבנאי. אין לי מושג למה זה ככה, אני חושב שזה איזשהו חוסר תשומת לב אצל מי שפיתח את השפה, סה”כ לא נראה לי שמישהו יחשוב שזאת פרקטיקה טובה להגדיר שיטה בשם הבנאי, אבל ככה זה.

בכל אופן, כיוון ש-B הוא לא בנאי, אז אי אפשר לשים בתוכו את הקריאה super(x) – קריאה שתפקידה להפנות לבנאי של האבא עם הפרמטר x. אבל הבעיה הנוספת יותר פתלתלה – כיוון של-B אין בנאי, אז יש לו את בנאי ברירת המחדל, הבנאי הריק. כמו כל בנאי, גם הבנאי הריק של B אמור לפנות קודם לבנאי של A לפני שהוא יתחיל לעבוד. אבל כיוון שהבנאי הוא בנאי ברירת מחדל ולא אנחנו כתבנו אותו, גם הפניה לבנאי של האבא משתמשת בבנאי ברירת המחדל. כלומר, הבנאי הריק של B מנסה לפנות לבנאי הריק של A.

אבל ל-A לעומת זאת יש בנאי, והוא לא ריק. ולכן בנאי ברירת המחדל לא קיים במחלקה הזאת, ולכן נקבל שגיאת קומפילציה מעצבנת שאומרת של-A אין בנאי ריק, למרות שאנחנו בכלל לא רצינו לקרוא לו.

(כמובן שאחרי שנוסיף בנאי ריק ל-A , נתקל בבעיה הקודמת – הפקודה super(x) שנמצאת במקום לא נכון).

הפתרון, ומה שאליו התכוון המשורר, הוא פשוט למחוק את המילה “void” מהכאילו בנאי של B, וזה יפתור את כל שגיאות הקומפילציה כאן, וגם ישיג את מה שהתכוון המתכנת לעשות.