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

 

חלקי קוד מעניינים של רב השלכתיות

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

interface CallBack{
  public void callBack();
}//end interface CallBack

 

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

 

מחלקה זו הגיעה לנקודה בה נפרק אותה לחלקים ונדון בהם בנפרד.

 

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

 

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

 

הבנאי למחלקת המורה החדשה שלנו מאתחל אובייקט וקטור.

 

class Teacher{
  Vector objList; //list of objects of type CallBack
  //----------------------------------------------//
    Teacher(){//constructor
    objList = new Vector();
  }//end constructor

 

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

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

  

  synchronized void register(CallBack obj){
    this.objList.addElement(obj);
    System.out.println(obj + " added");

  }//end register()

 

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

 

הקטע הבא הלקוח מתוך תיעוד JDK 1.1.3  מתאר את פונקצית removeElement() של מחלקת וקטור בה אנו משתמשים על מנת לעשות זאת (שלוש פונקציות שונות קיימות לשם הורדת אובייקטים מוקטור).

  

public final synchronized boolean removeElement(Object obj) 

This method removes the first occurrence of the argument from this vector. Indices beyond that point are adjusted appropriately 

Parameters: obj - the component to be removed. 

Returns: true if the argument was a component of this vector; false otherwise.

 

עקב מתן הגדרה זו, הקוד להורדת אובייקט מהרשימה הוא ישיר.

 

  synchronized void unRegister(CallBack obj){
    if(this.objList.removeElement(obj))
      System.out.println(obj + " removed");
    else System.out.println(obj + " not in the list");
  }//end register()

 

עכשיו אנו זקוקים לפונקציה על מנת לידע את כל האובייקטים ברשימה שמשהו מעניין קרה.
נכנה פונקציה זו
callTheRoll() על מנת לדבוק בדוגמת הכתה שלנו.

 

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

 

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

 

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

 

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

 

  void callTheRoll(){
    Vector tempList;//save a temporary copy of list here
        synchronized(this){
      tempList = (Vector)objList.clone();
    }//end synchronized block
    for(int cnt = 0; cnt < tempList.size(); cnt++){
      ((CallBack)tempList.elementAt(cnt)).callBack();
    }//end for loop
  }//end callTheRoll()

 

 

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

 

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

 

class Dog implements CallBack{
  String name;
//store name here for later ID
  //-----------------------------------------------------//
    Dog(String name){
//constructor
    this.name = name;
//save the name to identify the obj
  }//end constructor
  //-----------------------------------------------------//
  //An object of the Teacher class will invoke this method
  // as the callback mechanism to notify an object of this
  // class that something interesting has happened.
      public void callBack(){//announce callBack
    System.out.println("Woof, Woof " + name);

  }//end overridden callBack()
}//end class Dog

 

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

 

היכולת להוריד אובייקטים מהרשימה גם היא מוצגת.

 

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

 

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

 

class Callback02{
  public static void main(String[] args){
    //Instantiate Teacher object
    Teacher missJones = new Teacher();
    //Instantiate some Student objects
    Student tom = new Student("Tom");
    Student sue = new Student("Sue");
    Student peg = new Student("Peg");
    Student bob = new Student("Bob");
    Student joe = new Student("Joe");
    //Instantiate some Dog objects.
    Dog spot = new Dog("Spot");
    Dog fido = new Dog("Fido");
    Dog brownie = new Dog("Brownie");
    //Register some Student and Dog objects with the
     // Teacher object.
    System.out.println("Register Tom");
    missJones.register(tom);
    System.out.println("Register Spot");
    missJones.register(spot);
    System.out.println("Register Sue");
    missJones.register(sue);
    System.out.println("Register Fido");
    missJones.register(fido);
    System.out.println("Register Peg");
    missJones.register(peg);
    System.out.println("Register Bob");
    missJones.register(bob);
    System.out.println("Register Brownie");
    missJones.register(brownie);
    //Remove a Student object from the list.
    System.out.println("Remove Peg");
    missJones.unRegister(peg);
   //Try to remove an object that is not on the list.
    System.out.println("Try to remove Joe");
    missJones.unRegister(joe);
        System.out.println();//blank line
        //Cause the Teacher object to do a callBack on all
    // the objects on the list.

    missJones.callTheRoll();

  }//end main()
}//end class Callback02

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

הפלט מהרצת התוכנית מוצגת להלן. תוכל לראות את זיהוי כל אובייקט אינדיבידואלי כאשר הוא מתווסף או מורד מהרשימה.

 

שים לב שהניסיון להוריד את  Joe מהרשימה לא עלה יפה מכיוון שהוא לא נרשם מלכתחליה.

 

בסופו של דבר, תראה את הפלט המופק מעוררות callTheRoll() אשר בתורה מעוררת את פונקצית callBback() על כל אחד מהאובייקטים ברשימה.

 

שים לב ש-Peg לא הופיע ב-rollcall שכן הוא נוסף ראשון ואז הורד מהרשימה לפני שהתבצע
ה-
rollcall…

 

Register Tom
Student@1cc73e added
Register Spot
Dog@1cc74e added
Register Sue
Student@1cc741 added
Register Fido
Dog@1cc751 added

Register Peg
Student@1cc744 added
Register Bob
Student@1cc747 added
Register Brownie
Dog@1cc754 added
Remove Peg
Student@1cc744 removed
Try to remove Joe
Student@1cc74a not in the list
Tom here
Woof, Woof Spot
Sue hereWoof,
Woof FidoBob hereWoof,
Woof Brownie

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

 02-12-03 / 22:23  נוצר ע"י רונית רייכמן  בתאריך 
 תוכנית דוגמא רב השלכתית - הקודםהבא - רישום תוכנית רבת-משתתפים 
תגובות הקוראים    תגובות  -  0
דרכונט
מהי מערכת הדרכונט?
אינך מחובר, להתחברות:
דוא"ל
ססמא
נושאי לימוד
חיפוש  |  לא פועל
משלנו  |  לא פועל
גולשים מקוונים: 6