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

                                             בנאים

 

- העמסת בנאים

- בנאי ברירת מחדל

- יצירת אובייקטים על ה‑ערימה

- OutOfMemoryError

- בנאים והורשה

- יצירת אובייקטים בקריאה למתודות

- בנאים ובקרת גישה

 

 

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

 

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

 

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

 

העמסת בנאים

 

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

 

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

 

אוסף זהה של משתני מופע עשוי להיות מאותחל בצורות שונות תוך שימוש בהעמסת בנאים.

לדוגמה, אובייקט, שמאחסן תאריך, ניתן לאתחל באמצעות מחרוזת בפורמט "mm/dd/yy",
אך ניתן לאתחל אותו גם באמצעות שלושה ערכי
integer, עבור היום, החודש והשנה.
במקרה זה, ניתן להגדיר שני בנאים, שכל אחד מהם יקבל את נתוני האתחול בפורמט שונה
וימיר את הנתונים לפורמט הנחוץ כדי לאתחל את משתני המופע באובייקט מאותו טיפוס.

 

בנאי ברירת המחדל

 

ב‑Java וגם ב‑++C, הגדרת הבנאי איננה הכרחית. בשתי השפות, אם לא תגדיר בנאי,
יסופק עבורך אוטומטית בנאי ברירת המחדל.

 

ב‑Java בנאי ברירת המחדל מאתחל אוטומטית את כל משתני המופע כאפס, או כשווה ערך של אפס.

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

 

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

 

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

 

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

 

יצירת אובייקטים על ה‑ערימה

 

ב‑Java ניתן ליצור אובייקטים רק על ה‑ ערימה

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

 

במילים אחרות, על מנת ליצור אובייקט ב‑Java, עליך

·       להשתמש באופרטור new כדי לבקש זיכרון ממערכת ההפעלה בזמן ריצה

·       להשתמש בבנאי על מנת ליצור את האובייקט בזיכרון שקיבלת

 

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

 

התחביר ליצירת אובייקט שונה ב‑Java וב‑++C .

 

ההוראות הבאות מראות את השימוש האופייני בבנאי על מנת להצהיר, ליצור ולאתחל (כאופציה) אובייקט ב‑Java :

 

MyClass myObject = new MyClass();
MyClass myObject = new MyClass(1,2,3);

 

ההוראות מבצעות שלוש פעולות יחד:

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

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

·       האובייקט מאותחל באמצעות קריאה לבנאי בשם MyClass.

 

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

במקרה השני נקרא בנאי פרמטרי, והפרמטרים 1,2,3 מועברים לו.

 

OutOfMemoryError

 

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

 

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

 

יצירת אובייקטים בקריאה למתודות

 

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

 

הן ב‑Java והן ב‑++C, ניתן גם לקרוא לבנאי מבלי להשׂים את ההצבעה למשתנה בצורה גלויה. מקובל לקרוא לכך אובייקט אנונימי.

 

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

 

obj.myFunction(
  new myClassConstructor(1,2,3) );//Java version

 

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

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

 

הן ב‑Java והן ב‑++C, כאשר מתחיל הביצוע של פונקציה או מתודה, כל הפרמטרים נוצרים כמשתנים מקומיים מטיפוס automatic. (משתני automatic חדלים להתקיים עם סיום המתודה.) ב‑Java כל המשתנים הם automatic .

 

נוסף על משתני  ++automatic, C תומכת גם במשתני static, שאינם חדלים להתקיים עם סיום הפונקציה.

 

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

 

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

ב‑Java, מכיוון שהמשתנה יהיה automatic, הרי שעם סיום המתודה הוא יהיה מוּעָד לאיסוף אשפה.

ב‑++C, מכיוון שהמשתנה הוא automatic, הרי שעם סיום המתודה הוא יושמד.

 

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

 

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

 

להלן אפליקציית Java אשר ממחישה כמה מהמושגים הנ"ל לגבי בנאים.

 

זוהי אפליקציית Java שממחישה:

1. יצירת אובייקט באמצעות קריאה לבנאי ברירת המחדל.

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

 

התוכנית נבדקה עם 1.1.3 JDK תחת Win95 .

 

/*File cnstrct1.java Copyright 1997, R.G.Baldwin
This is a Java application which illustrates:
1.  Instantiating an object by calling the default 
constructor.
2.  Instantiating an object by calling a parameterized 
constructor as a parameter to a function call.

The program was tested using JDK 1.1.3 under Win95.

The program displays the following output:

Starting Program
Object contains 100
**********************************************************/

class NewClass{
  int instanceVar;
  //-----------------------------------------------------//
  
  NewClass(int inData){//parameterized constructor
    instanceVar = inData; //save inData
  }//end parameterized constructor
  //-----------------------------------------------------//

  void showInstanceVar(){
    System.out.println("Object contains " + instanceVar);
  }//end showInstanceVar
}//end NewClass
//=======================================================//

class cnstrct1 { //define the controlling class
  //The following method receives an object and calls one
  // of the methods of the object to display the data 
  // contained in the object.
  void myFunction(NewClass objIn){
    objIn.showInstanceVar();
  }//end myFunction
  //-----------------------------------------------------//
  
  public static void main(String[] args){ //main method
    System.out.println("Starting Program");
        
    //Instantiate an object of this type by calling 
    // default constructor for the controlling class
    cnstrct1 obj = new cnstrct1();
        
    //Call instance method with call to parameterized 
    // constructor as a parameter
    obj.myFunction(new NewClass(100));
  }//end main

}//End cnstrct1 class.  

 

 

בנאים והורשה

 

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

 

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

 

ב‑++C משיגים זאת תוך שימוש בתחביר מסובך למדי בהגדרה של הבנאי. ב‑Java התחביר מורכב פחות.

 

ב‑Java, על מנת להפעיל את הבנאי שבמחלקת-העל לפני ביצוע גוף הבנאי שבתת-המחלקה, עליך פשוט לכלול כהוראה הראשונה בבנאי שבתת-המחלקה את ההוראה הבאה:

 

super(optional parameters);

 

 

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

 

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

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

 

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

 

זוהי אפליקציית Java אשר מרחיבה את האפליקציה cnstrct1.java.

 

נוסף על המושגים שהומחשו באותה אפליקציה, אפליקציה זו ממחישה את השימוש ב‑super()
בבנאי של תת-מחלקה על מנת לקרוא לבנאי של מחלקת-העל.

 

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

 

כמו כן שים לב, שהתוכנית לא תהודר אם תופיע הוראת output לפני הקריאה ל‑super() בבנאי
של תת-המחלקה.

 

התוכנית מציגה את הפלט הבא:

 

/*File cnstrct2.java Copyright 1997, R.G.Baldwin
This is a Java application which extends the application 
named cnstrct1.java.  

In addition to the concepts illustrated in that 
application, this application illustrates the use of 
super() in a subclass constructor to call the constructor 
in the superclass.

Note that this program will not compile unless the 
replacement for the default constructor is provided.

Note also that the program will not compile if an output 
statement is placed ahead of the call to super() in the 
subclass constructor.

The program displays the following output:

Starting Program
Default constructor invoked
Entering SuperClass constructor
Back in SubClass constructor
Object contains 100

**********************************************************/

class SuperClass{
  int instanceVar;
  
  SuperClass(){//replacement for default constructor
    System.out.println("Default constructor invoked");
  }//end default constructor
  //-----------------------------------------------------//

  SuperClass(int inData){//parameterized constructor
    System.out.println("Entering SuperClass constructor"); 
    instanceVar = inData;//put inData in instance variable
  }//end parameterized constructor
  //-----------------------------------------------------//

  void showInstanceVar(){
    System.out.println("Object contains " + instanceVar);
  }//end showInstanceVar
}//end SuperClass
//=======================================================//

class SubClass extends SuperClass{
  SubClass(int incomingData){// constructor
    //The following statement will not compile.  The call 
    // to super() must be the first thing in a method if 
    // it appears at all.
    //System.out.println("Entering SubClass constructor"); 
    super(incomingData);//call the SuperClass constructor
    System.out.println("Back in SubClass constructor");
  }//end SubClass constructor
}//end SubClass
//=======================================================//

class cnstrct2 { //define the controlling class
  //The following method receives an object and calls one 
  // of the methods of the object to display the data 
  // contained in the object. In this case, both the 
  // method and the instance variable are inherited from 
  // the SuperClass.
  void myFunction(SubClass objIn){
    objIn.showInstanceVar();
  }//end myFunction
  //-----------------------------------------------------//
  
  public static void main(String[] args){ //main method
    System.out.println("Starting Program");
    
    //Instantiate an object of the SuperClass type to
    // illustrate the requirement for the default 
    // constructor in the SuperClass class
    new SuperClass();
  
    //Instantiate an object of this type by calling
    // default constructor
    cnstrct2 obj = new cnstrct2();
  
    //Call function with call to parameterized SubClass 
    // constructor as a parameter.  The constructor in the
    // subclass passes the parameter along to the 
    // constructor in the superclass.
    obj.myFunction(new SubClass(100));
  }//end main

}//End cnstrct2 class.  

 

בנאים ובקרת גישה

 

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

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

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

 

כל קוד, בכל אובייקט יהיה מסוגל לגשת לאובייקט וליצור אובייקט של כל מחלקה, בכל חבילה,
אם היא מצוינת כ‑
Public (אלא אם כן, היא גם מצוינת כ‑abstract, ובמקרה כזה, לא ניתן ליצור מתוכה כלל).
מבחינת מחלקות, לא קיימים אמצעי הגישה
private או protected, רק public, abstract ו‑final. אמצעי הגישה abstract ו‑final שוללים זה את זה הדדית.

 

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

 

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

 

הכללים הנ"ל תקפים כאשר אתה משתמש באמצעי גישה לגבי מחלקות. על פי ה‑The Java Tutorial, ניתן גם להשתמש באמצעי גישה ישירות לגבי הבנאי, ואז מתקבלות התוצאות הבאות:

 

private

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

 

protected

רק תת-מחלקות של המחלקה שלך יוכלו ליצור מופעים שלה.

 

public

כל אחד יוכל ליצור מופעים של המחלקה שלך.

 

package

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

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