» נושאי לימוד
» נושאי לימוד
יום שני 29 באפריל 2024
השורה התחתונה בנושא ממשקים
דף ראשי  מתחילים  עוד בנושא ממשקים  השורה התחתונה בנושא ממשקים גרסה להדפסה

השורה התחתונה בנושא ממשקים

 

מהי, אם כן, השורה התחתונה בנושא ממשקים? למה באמת הם טובים?

 

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

 

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

 

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

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

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

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

בדרך כלל, לא ניתן להפעיל על אובייקט מהטיפוס הכללי Object מתודות אחרות מלבד אלו,

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

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

 

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

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

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

 

קטעי קוד מעניינים

 

התוכנית הבאה ממחישה את השימוש בממשק על מנת לאפשר למתודה בשם compare()
במחלקה
LibraryClass להפעיל את המתודות של אובייקטים נכנסים כטיפוס הכללי Object.

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

 

הפלט שמפיקה התוכנית מוצג בהערות המופיעות בה.

 

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

המחלקה השנייה קרויה UserClass, והיא משתמשת בממשק בשם Intfc02A. אובייקטים של מחלקה זו מתאימים להעברה כטיפוסי Object למתודה compare(), אשר מטפלת בהם.

המחלקה השלישית קרויה LibraryClass. היא מכילה את המתודה compare(),
אשר משמשת לטיפול באובייקטים מטיפוס לא-ידוע
(למעשה, האובייקטים הם מטיפוס
UserClass, אבל רק אנחנו יודעים זאת).

הראשון מבין קטעי הקוד המעניינים מופיע במחלקה השולטת Intfc02, אשר מבצעת את שתי המחלקות האחרות. ההוראה הבאה אופיינית לקוד שנוכל למצוא במחלקה השולטת.
הוא יוצר שני אובייקטים מטיפוס
UserClass ומעביר אותם למתודה compare() של אובייקט חדש מטיפוס LibraryClass.

 

new LibraryClass().compare(
                        new UserClass(5),new UserClass(6));

 

הקטע הבא הוא קטע קוד של המחלקה UserClass, שהאובייקטים שלה מתאימים להעברה אובייקט של המחלקה LibraryClass לצורך העיבוד. הם מתאימים משום ש‑UserClass משתמשת בממשק Intfc02A, הדרוש למתודה compare() של המחלקה LibraryClass.

הודות להגדרת המתודות GT,EQ,LT, המחלקה LibraryClass מאפשרת למתודה compare() להפעיל את שלוש המתודות הללו על מנת להשוות בין אובייקטים מטיפוס UserClass.

מאידך, הודות לשימוש בממשק Intfc02A, המחלקה UserClass מאפשרת למתודה compare() של המחלקה LibraryClass לקבל אובייקטים מטיפוס זה בתור הטיפוס הכללי Object (מבלי שהיא יודעת מה הטיפוס האמיתי שלהם) ולהמיר אותם לטיפוס Intfc02A על מנת שיוכלו להפעיל את המתודות של UserClass.

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

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

 

שלוש המתודות דומות מאוד זו לזו, ועל כן נביא כאן רק אחת, המתודה LT.

ראשית, שים לב, שהמחלקה משתמשת בממשק Intfc02A, הנדרש על ידי המתודה compare().

כמו כן, שים לב, שכאשר המתודה LT מופעלת על אובייקט מטיפוס UserClass, היא מקבלת למעשה כפרמטר אובייקט מטיפוס Object.
האובייקט, שעליו מופעלת המתודה (
this), אמור להיות מושווה לאובייקט שמועבר כפרמטר.
המתודה ממירה את האובייקט הנכנס לטיפוס שלה-עצמה (
UserClass) על מנת שתוכל לגשת למשתנה המופע data, המגיע עם האובייקט.
(אחרת, לא ניתן היה לגשת למשתנה המופע הנ"ל.)

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

 

class UserClass implements Intfc02A{
  int data;
  
  public boolean LT(Object obj){//test for less than
    if(this.data < ((UserClass)obj).data)return true;
    else return false;
  }//end LT()

  //...

 

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

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

 

המתודות המשוות עצמן מוגדרות במחלקה של האובייקטים הנכנסים. המתודה compare() של האובייקט מהמחלקה LibraryClass ממירה את האובייקטים הנכנסים לטיפוס של הממשק
(
Intfc02A) ומפעילה את מתודות המופע של אותם אובייקטים.

אף על פי שהמתודה compare() מפעילה שלוש מתודות שונות על האובייקטים הנכנסים,
כל הפעלה כזו דומה לאחרות, ועל כן רק ההפעלה של המתודה 
LT מובאת כאן.

שים לב, שהמתודה compare() מקבלת שני אובייקטים נכנסים מטיפוס כללי Object,
וממירה רק אחד מהם לטיפוס של הממשק על מנת להפעיל את המתודות שלו, בעוד שהאובייקט האחר מועבר למתודה בלא שינוי (ללא המרה). (זכור, שהאובייקט הזה מומר לאחר מכן לטיפוס
UserClass בתוך המתודה של המחלקה UserClass, שאליה הוא מועבר.)

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

 

class LibraryClass{
  void compare(Object objA,Object objB){
    System.out.println("objA less than objB? " 
                             + ((Intfc02A)objA).LT(objB) );
  //...
  }//end compare() method
}//end LibraryClass

 

את הקוד שהושמט מהתוכנית המלאה, ניתן לראות למטה.

להלן הגדרת הממשק.

 

הגדרת ממשק עבור intfc02.java, הממחישה את השימוש בממשק.

 

/*File Intfc02A.java Copyright 1997, R.G.Baldwin
Interface definition used to support Intfc02.java
Illustrates use of interface.
*/

public interface Intfc02A{
  public boolean LT(Object obj);//test less than
  public boolean GT(Object obj);//test greater than
  public boolean EQ(Object obj);//test equal to  
}//end interface Intfc02A

 

 06-01-04 / 19:58  נוצר ע"י רונית רייכמן  בתאריך 
 מהו ממשק, ולשם מה הוא טוב? - הקודםהבא - התוכנית המלאה 
תגובות הקוראים    תגובות  -  0
דרכונט
מהי מערכת הדרכונט?
אינך מחובר, להתחברות:
דוא"ל
ססמא
נושאי לימוד
חיפוש  |  לא פועל
משלנו  |  לא פועל
גולשים מקוונים: 8