לא ניתן להתייחס ל- "X" לפני שהתקשר לבנאי העל

1. סקירה כללית

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

2. שרשרת קונסטרוקטורים

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

אנו יכולים להתקשר לבנאי מאותו מחלקה עם מילת המפתח זֶה, או שנוכל להתקשר לבנאי מעמד העל עם מילת המפתח סוּפֶּר.

כאשר קונסטרוקטור לא מתקשר לבנאי אחר, המהדר מוסיף קריאה לבנאי ללא ויכוח של מעמד העל.

3. שגיאת האוסף שלנו

שגיאה זו מסתכמת ב מנסה לגשת לחברים ברמת מופע לפני שאנחנו קוראים לשרשרת הבנאים.

בואו נראה כמה דרכים שאנחנו יכולים להיתקל בזה.

3.1. הכוונה לשיטת מופע

בדוגמה הבאה נראה את שגיאת האוסף לא ניתן להתייחס ל- "X" לפני שקראו לבנאי העל בשורה 5. שים לב כי בונה מנסה להשתמש בשיטת המופע getErrorCode () מוקדם מדי:

מחלקה ציבורית MyException מרחיבה RuntimeException {private int errorCode = 0; MyException ציבורי (הודעת מחרוזת) {super (הודעה + getErrorCode ()); // שגיאת אוסף} ציבורי int getErrorCode () {return errorCode; }} 

שגיאות זה בגלל, until סוּפֶּר() הסתייםאין מופע של הכיתה MyException. לכן, אנחנו עדיין לא יכולים להתקשר לשיטת המופע getErrorCode ().

3.2. הכוונה לשדה מופע

בדוגמה הבאה אנו רואים את החריג שלנו עם שדה מופע במקום שיטת מופע. בואו נסתכל איך הקונסטרוקטור הראשון מנסה להשתמש בחבר מופע לפני שהמופע עצמו מוכן:

מחלקה ציבורית MyClass {private int myField1 = 10; פרטי int myField2; MyClass ציבורי () {this (myField1); // שגיאת אוסף} MyClass ציבורי (int i) {myField2 = i; }}

הפניה לשדה מופע יכולה להיעשות רק לאחר איתחול המחלקה שלו, כלומר לאחר כל קריאה ל זֶה() אוֹ סוּפֶּר().

אם כך, מדוע אין שגיאת מהדר בבנאי השני, המשתמש גם בשדה מופע?

זכור את זה כל הכיתות נגזרות באופן מרומז מהכיתה לְהִתְנַגֵד, וכך יש מרומז סוּפֶּר() שיחה שנוספה על ידי המהדר:

MyClass ציבורי (int i) {super (); // נוסף על ידי המהדר myField2 = i; } 

פה, לְהִתְנַגֵדבונה נקרא לפני שניגש אליו myField2, כלומר אנחנו בסדר.

4. פתרונות

הפתרון האפשרי הראשון לבעיה זו הוא טריוויאלי: אנחנו לא קוראים לבנאי השני. אנו עושים במפורש בבנאי הראשון את מה שרצינו לעשות בבנאי השני.

במקרה זה נעתיק את הערך של myField1 לְתוֹך myField2:

מחלקה ציבורית MyClass {private int myField1 = 10; פרטי int myField2; MyClass ציבורי () {myField2 = myField1; } MyClass ציבורי (int i) {myField2 = i; }} 

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

אבל אם אנו מתקשרים לבנאי השני מסיבה טובה, למשל, כדי למנוע חזרה על קוד, נוכל להעביר את הקוד לשיטה:

מחלקה ציבורית MyClass {private int myField1 = 10; פרטי int myField2; MyClass ציבורי () {setupMyFields (myField1); } MyClass ציבורי (int i) {setupMyFields (i); } setup ריק ריק MyFields (int i) {myField2 = i; }} 

שוב, זה עובד מכיוון שהמהדר התקשר באופן מרומז לשרשרת הבונים לפני שהוא קורא לשיטה.

פתרון שלישי יכול להיות שאנחנו משתמשים בו שדות או שיטות סטטיות. אם נשנה myField1 לקבוע סטטי, אז גם המהדר שמח:

מחלקה ציבורית MyClass {final private final int SOME_CONSTANT = 10; פרטי int myField2; MyClass ציבורי () {this (SOME_CONSTANT); } MyClass ציבורי (int i) {myField2 = i; }} 

עלינו לציין כי ביצוע שדה סטָטִי פירושו שהוא הופך להיות משותף עם כל המקרים של האובייקט הזה, כך שזה לא שינוי בקלילות יתרה.

ל סטָטִי כדי להיות התשובה הנכונה, אנו זקוקים לסיבה חזקה. לדוגמא, אולי הערך הוא לא ממש שדה, אלא קבוע, ולכן הגיוני לעשות את זה סטָטִי ו סופי. אולי שיטת הבנייה שרצינו להתקשר אליה אינה זקוקה לגישה לחברי המעמד של הכיתה, כלומר היא צריכה להיות סטָטִי.

5. מסקנה

ראינו במאמר זה כיצד מתייחסים לחברי מופע לפני סוּפֶּר() אוֹ זֶה() שיחה נותנת שגיאת אוסף. ראינו את זה קורה עם מעמד בסיס שהוכרז במפורש וגם עם המשתמע לְהִתְנַגֵד כיתת בסיס.

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

כמו תמיד ניתן למצוא את קוד המקור לדוגמא זו ב- GitHub.


$config[zx-auto] not found$config[zx-overlay] not found