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

נתון קוד הבא:



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


בחרו בטענה הנכונה ביותר:


א. הקוד אינו סותר עקרון של הכמסה


ב. משה צודק, והקוד המתוקן יראה כך:


ג. משה צודק, והקוד המתוקן יראה כך:


ד. משה צודק, והקוד המתוקן יראה כך:


ה. משה צודק, והקוד המתוקן יראה כך:
העתק שאלה
שתף שאלה
סמן כחשוב
סמן כבוצע
אוניברסיטת בר-אילןמועד א2024סמסטר ב
הסתרת מידעמחלקותאובייקטיםמעקב אחר קוד
בדקו את תכונות הטיפוסים המעורבים: הטיפוס הפרימיטיבי int ומחלקת העטיפה Integer. האם ניתן לשנות את ערכם מבחוץ לאחר שהועברו כפרמטר או הוחזרו ממתודה?
הטענה הנכונה היא א'. הקוד אינו סותר את עקרון ההכמסה (Encapsulation).

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


במקרה הנתון:
1. השדה x מוגדר כ-private. זהו הצעד הראשון והבסיסי במימוש הכמסה, המונע גישה ישירה לשדה מחוץ למחלקה.

2. המתודה get() מחזירה את ערכו של x. מכיוון ש-x הוא מטיפוס פרימיטיבי (int), המתודה מחזירה העתק של הערך. כל שינוי שהקוד הקורא יבצע על הערך המוחזר לא ישפיע על השדה x המקורי באובייקט.

3. המתודה set(Integer x) מקבלת כפרמטר אובייקט מטיפוס Integer. במבט ראשון, זה עלול להיראות כמקור לבעיה, שכן אנו מעבירים אובייקט (שהוא reference type) שעשוי לאפשר שינוי של המצב הפנימי. עם זאת, המחלקה Integer ב-Java היא Immutable (בלתי ניתנת לשינוי). מרגע שנוצר אובייקט Integer עם ערך מסוים, לא ניתן לשנות את הערך הזה. בנוסף, השורה this.x = x; מבצעת תהליך הנקרא Unboxing, שבו הערך הפרימיטיבי int מתוך אובייקט ה-Integer מועתק אל תוך השדה הפרימיטיבי this.x.


מאחר שהשדה x הוא פרימיטיבי והטיפוס Integer הוא בלתי ניתן לשינוי, לא קיימת "דליפת ייצוג" (representation leak). לא ניתן לקבל רפרנס למצב הפנימי של האובייקט ולשנות אותו באופן בלתי מבוקר. לכן, עקרון ההכמסה נשמר במלואו.


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

* ג', ה': שימוש ב-clone() (יצירת "עותק הגנתי") נדרש כאשר עובדים עם אובייקטים שהם Mutable (ניתנים לשינוי). מכיוון ש-Integer הוא immutable (ו-int פרימיטיבי), אין בכך צורך, ולמעשה למחלקה Integer אין מתודת clone() ציבורית.

* ד': שינוי הפרמטר לטיפוס פרימיטיבי int הוא שינוי סגנוני קביל, אך הוא אינו "מתקן" את הקוד המקורי, מכיוון שהקוד המקורי תקין לחלוטין מבחינת עקרון ההכמסה.