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

בג'אווה, מה מבין הבאים לא יכולה להיות תוצאת הרצת המתודה isWonderful?

תזכורת: equals היא מתודה המוגדרת במחלקה Object ואשר מחזירה true רק אם עצם הקלט שווה בתוכנו לעצם שקרא למתודה. ניתן להניח כי כל המחלקות מממשות את equals כנדרש.




.1 לא ייתכן שהמתודה תחזיר wonder
.2 לא ייתכן שהמתודה תחזיר won

.3 לא ייתכן שייזרק חריג מסוג NullPointerException

.4 לא ייתכן שהמתודה תחזיר wonful
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
אוניברסיטת בר-אילןמועד א2023סמסטר ב
מעקב אחר קודאובייקטיםחריגות
נתחו את מצב המצביעים o1 ו-o2 רגע לפני ביצוע התנאי השני (!o1.equals(o2)). שימו לב כיצד התנאי והפקודות בבלוק ה-if הראשון משפיעים על מצבם.
התשובה הנכונה היא 4. לא ייתכן שהמתודה תחזיר wonful.

ננתח את זרימת המתודה isWonderful:
1. המשתנה s מאותחל למחרוזת "won".

2. התנאי הראשון, if (o1 != o2), בודק שוויון מצביעים (reference equality). כלומר, האם o1 ו-o2 מצביעים לאותו אובייקט בזיכרון.

3. התנאי השני, if (!o1.equals(o2)), בודק שוויון תוכני (content equality). כלומר, האם האובייקטים שקולים בתוכנם, על פי המימוש של המתודה equals.


כעת נבחן את כלל המקרים האפשריים (בהנחה שלא נזרק חריג):


מקרה א': `o1` ו-`o2` מצביעים לאותו אובייקט (`o1 == o2`).
- התנאי הראשון (o1 != o2) יתקיים כ-false.

- גוף ה-if הראשון לא יתבצע, והמשתנה s יישאר "won".

- נגיע לתנאי השני (!o1.equals(o2)). מכיוון ש-o1 ו-o2 הם אותו מצביע, ובהתאם לחוזה של equals, הביטוי o1.equals(o2) חייב להחזיר true.

- לכן, התנאי !o1.equals(o2) יתקיים כ-false.

- גוף ה-if השני לא יתבצע.

- המתודה תחזיר "won".


מקרה ב': `o1` ו-`o2` מצביעים לאובייקטים שונים (`o1 != o2`).
- התנאי הראשון (o1 != o2) יתקיים כ-true.

- גוף ה-if הראשון יתבצע:

- המצביע o1 יקבל את ערך המצביע o2 באמצעות הפקודה o1 = o2. כעת, `o1` ו-`o2` מצביעים לאותו אובייקט.

- למשתנה s תתווסף המחרוזת "der", וערכו יהיה "wonder".

- נגיע לתנאי השני (!o1.equals(o2)). מכיוון שכעת o1 ו-o2 הם אותו מצביע, הביטוי o1.equals(o2) חייב להחזיר true.

- לכן, התנאי !o1.equals(o2) יתקיים כ-false.

- גוף ה-if השני לא יתבצע.

- המתודה תחזיר "wonder".


בשני המקרים, התנאי השני (!o1.equals(o2)) תמיד מתקיים כ-false. הסיבה לכך היא שבזמן הערכת התנאי, המשתנים o1 ו-o2 תמיד יחזיקו את אותו המצביע. לכן, גוף ה-if השני, s += "ful";, הוא למעשה קוד בלתי נגיש (unreachable code).


מכאן נובע שהמחרוזת "ful" לעולם לא תתווסף ל-s, וכל פלט המכיל אותה אינו אפשרי. לכן, לא ייתכן שהמתודה תחזיר "wonful".


בדיקת שאר האפשרויות:
- wonder: אפשרי, למשל isWonderful(new String("a"), new String("b")).

- won: אפשרי, למשל Object obj = new Object(); isWonderful(obj, obj).

- NullPointerException: אפשרי. למשל, אם o2 הוא null ו-o1 אינו null, אז בתוך ה-if הראשון o1 יהפוך ל-null, והקריאה o1.equals(o2) תזרוק חריג. גם אם שניהם null מההתחלה, הקריאה ל-equals תזרוק חריג.