שאלת מבחן בתכנות מונחה עצמים - אוניברסיטת בר-אילן 2016 - חריגות

סעיף א (10 מתוך 20 נקודות): מה יהיה הפלט של התוכנית הבאה:



סעיף ב (10 מתוך 20 נקודות):


מה תהיה התשובה אם נשנה את 4 השורות הראשונות של הקוד ל:


העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
אוניברסיטת בר-אילןמועד א2016סמסטר ב
חריגותירושהפולימורפיזםמעקב אחר קודמחלקותאובייקטים
עקבו אחר זריקת והתפשטות החריגות בין המתודות. שימו לב כיצד היררכיית הירושה קובעת איזה בלוק catch יתפוס כל חריגה, וזכרו שבלוק finally מתבצע תמיד.
### סעיף א

ראשית, ננתח את היררכיית המחלקות המטפלות בחריגות:
- E1 יורשת מ-Exception.

- E3 יורשת מ-E1.

- E2 יורשת מ-E3. לכן, אובייקט מטיפוס E2 הוא גם instanceof E3 וגם instanceof E1 (פולימורפיזם).

- E4 יורשת מ-E1. לכן, אובייקט מטיפוס E4 הוא גם instanceof E1.


כעת נעקוב אחר זרימת התוכנית:
1. המתודה main קוראת ל-f1().

2. המתודה f1() קוראת ל-f2().

3. בתוך f2(), נזרקת חריגה (Exception) חדשה מסוג E2.

4. לפני שהמתודה f2() מסיימת את פעולתה (עקב החריגה), בלוק ה-finally שלה מתבצע ומדפיס:

f2-finally

5. החריגה מסוג E2 מתפשטת חזרה למתודה f1(), שקראה ל-f2().

6. מערכת ה-try-catch ב-f1() מנסה לתפוס את החריגה. הבלוק הראשון הוא catch (E3 e). מכיוון ש-E2 היא מחלקת בת של E3, החריגה נתפסת על ידי בלוק זה. הפלט המודפס הוא:

f1-catch-E3

7. בתוך בלוק ה-catch, נזרקת חריגה חדשה מסוג E4.

8. בלוקי ה-catch הבאים ב-f1() (עבור E4) אינם נבדקים, כיוון שהחריגה המקורית (E2) כבר נתפסה. החריגה החדשה (E4) תתפשט הלאה.

9. לפני שהמתודה f1() מסיימת עקב החריגה החדשה, בלוק ה-finally שלה מתבצע ומדפיס:

f1-finally

10. החריגה מסוג E4 מתפשטת חזרה למתודה main.

11. מערכת ה-try-catch ב-main מנסה לתפוס את החריגה. הבלוק הראשון הוא catch (E1 e). מכיוון ש-E4 היא מחלקת בת של E1, החריגה נתפסת כאן.

12. הפקודה e.getClass().getSimpleName() מדפיסה את שם המחלקה *האמיתי* של האובייקט שנתפס, כלומר E4.

E4

13. לפני שהמתודה main מסיימת, בלוק ה-finally שלה מתבצע ומדפיס:

main-finally


הפלט הסופי של סעיף א':
f2-finally
f1-catch-E3
f1-finally
E4
main-finally


### סעיף ב


כעת, היררכיית הירושה משתנה:
- E2 יורשת מ-Exception.

- E1 יורשת מ-E2.

- E3 יורשת מ-Exception.

- E4 יורשת מ-Exception.

כעת, E2, E3, ו-E4 הן מחלקות אחיות, ואין ביניהן קשר ירושה ישיר.


נעקוב שוב אחר זרימת התוכנית:
1. המתודה main קוראת ל-f1().

2. המתודה f1() קוראת ל-f2().

3. בתוך f2(), נזרקת חריגה חדשה מסוג E2.

4. בלוק ה-finally של f2() מתבצע ומדפיס:

f2-finally

5. החריגה מסוג E2 מתפשטת חזרה למתודה f1().

6. מערכת ה-try-catch ב-f1() מנסה לתפוס את החריגה:

- catch (E3 e): האם E2 הוא instanceof E3? לא. הם אחים בהיררכיה. הבלוק מדולג.

- catch (E4 e): האם E2 הוא instanceof E4? לא. הם אחים בהיררכיה. הבלוק מדולג.

7. מאחר ואף בלוק catch ב-f1() לא תפס את החריגה, היא ממשיכה להתפשט כלפי מעלה.

8. לפני שהמתודה f1() מסיימת (בשל התפשטות החריגה), בלוק ה-finally שלה מתבצע ומדפיס:

f1-finally

9. החריגה מסוג E2 מתפשטת חזרה למתודה main.

10. מערכת ה-try-catch ב-main מנסה לתפוס את החריגה:

- catch (E1 e): האם E2 הוא instanceof E1? לא. למעשה, היחס הפוך (E1 יורשת מ-E2). הבלוק מדולג.

- catch (Exception e): האם E2 הוא instanceof Exception? כן. החריגה נתפסת כאן. הפלט המודפס הוא:

EXCEPTION

11. לפני שהמתודה main מסיימת, בלוק ה-finally שלה מתבצע ומדפיס:

main-finally


הפלט הסופי של סעיף ב':
f2-finally
f1-finally
EXCEPTION
main-finally

lacksquare