תכנות מונחה עצמים (OOP) - בנאים (Constructors)

סגור באמצעות טופס זה תוכלו לספר ולהמליץ לחבריכם..
שם השולח:
כתובת דוא"ל של השולח:
שם המקבל:
שלח לכתובת דוא"ל:
הוסף הערה:
שפת #C מאפשרת להגדיר מתודות מיוחדות הנקראות בנאים (Constructors או ctor בקיצור). מתודת הבנאי (Ctor) מופעלת פעם אחת בחיי אובייקט, ופעם אחת בלבד, כחלק מתהליך יצירת האובייקט.

בנאים (Constructorsבנאים

 
מאת: ארז קלר

הורדת דוגמת קוד


שפת C# מאפשרת להגדיר מתודות מיוחדות הנקראות בנאים (Constructors או ctor בקיצור).
מתודת הבנאי (Ctor) מופעלת פעם אחת בחיי אובייקט, ופעם אחת בלבד, כחלק מתהליך יצירת האובייקט.
מהו תפקיד מתודת הבנאי?,
למתודת הבנאי תפקיד כפול: הקצאת האובייקט ואתחול התכונות.
מאחורי הקלעים ובצורה שקופה למתכנת מתודת הבנאי היא זו שיוצרת את האובייקט,
בנוסף הבנאי מאתחל תכונות המחלקה בערך ראשוני .
בנאי אם כך, תפקידו כפול:
הקצאת האובייקט (שקוף למתכנת), ואתחול תכונות המחלקה.
יתכן והאתחול יאפס את ערכי התכונות או לחילופין יבצע להן השמה על פי ערכים אשר מתקבלים כפרמטרים.
עם סיום פעולתו, הבנאי מחזיר את כתובתו של האובייקט שזה עתה נוצר ואותחל לייחוס.
לכל מחלקה מוגדר לפחות מתודת בנאי אחת, במידה ולא נגדיר מתודת בנאי היא תוגדר בצורה מרומזת ומעבר ליצירת האובייקט היא תאפס את ערכיו, בנאי זה נקרא בנאי ברירת מחדל  (Default Ctor).
לדוגמה (CtorSample01):


 1  : public class Point 
 2  : { 
 3  :     private int x; 
 4  :     private int y; 
 5  :     public void SetX(int x) 
 6  :     { 
 7  :         this.x = x; 
 8  :     } 
 9  :     public void SetY(int y) 
 10 :     { 
 11 :         this.y = y; 
 12 :     } 
 13 :     public void Print() 
 14 :     { 
 15 :         Console.WriteLine("X = {0}", x); 
 16 :         Console.WriteLine("Y = {0}", y); 
 17 :     } 
 18 : } 

שימו לב למחלקה Point,
האם כתבנו בה מתודת בנאי?, התשובה היא לא,
האם יש לה בנאי?, התשובה היא כן,
משום שלא הוגדר בה בנאי התווסף אליה בנאי ברירת מחדל בצורה מרומזת, בנאי ברירת המחדל מאפס את התכונות xו- y.

בדוגמה הבאה (CtorSample02) הוספנו בנאי שאינו מקבל פרמטרים:


 1  : public class Point 
 2  : { 
 3  :     private int x; 
 4  :     private int y; 
 5  :     public Point() 
 6  :     { 
 7  :          
 8  :     } 
 9  :     public void SetX(int x) 
 10 :     { 
 11 :         this.x = x; 
 12 :     } 
 13 :     public void SetY(int y) 
 14 :     { 
 15 :         this.y = y; 
 16 :     } 
 17 :     public void Print() 
 18 :     { 
 19 :         Console.WriteLine("X = {0}", x); 
 20 :         Console.WriteLine("Y = {0}", y); 
 21 :     } 
 22 : } 

נגדיר בנאי חסר פרמטרים (בשורה 5), גם במקרה זה הבנאי מאפס את תכונות המחלקה. שמה של מתודת הבנאי זהה לשם המחלקה, Point במקרה דנן. למתודת הבנאי לא מגדירים ערך מוחזר. למרות שלא נכתבה אף פקודה בגוף המתודה היא תדאג לאפס את תכונות המחלקה. למעשה, אין כל הבדל בינה לבין בנאי ברירת המחדל. ניתן כמובן לכתוב בה קוד שיאתחל את ערכי התכונות בערכים אחרים, לדוגמה:
public Point()
{
     int x = 1;
     int y = 1;
 }
 
למרות שלא הוגדר ערך מוחזר לבנאי הוא מחזיר ערך: הוא מחזיר את כתובתו של האובייקט שזה עתה נוצר:
Point p = new Point();
 
הערה: בנאי ברירת המחדל נוצר רק במקרה בו לא הוגדרה מתודת בנייה אחרת בצורה מפורשת, בדוגמה האחרונה לא יוגדר בנאי ברירת מחדל.
 
מתודת הבנאי יכולה, כמובן לקבל פרמטרים (כמו זו שבשורה 10), בדרך כלל הפרמטרים יכילו את הערכים הראשוניים של תכונות המחלקה (CtorSample03):
 1  : class Point 
 2  : { 
 3  :     private int x; 
 4  :     private int y; 
 5  :     public Point() 
 6  :     { 
 7  :         x = 1; 
 8  :         y = 1; 
 9  :     } 
 10 :     public Point(int x, int y) 
 11 :     { 
 12 :         this.x = x; 
 13 :         this.y = y; 
 14 :     } 
 15 :     public void SetX(int x) 
 16 :     { 
 17 :         this.x = x; 
 18 :     } 
 19 :     public void SetY(int y) 
 20 :     { 
 21 :         this.y = y; 
 22 :     } 
 23 :     public void Print() 
 24 :     { 
 25 :         Console.WriteLine("X = {0}", x); 
 26 :         Console.WriteLine("Y = {0}", y); 
 27 :     } 
 28 : } 
כפי שניתן להבחין בדוגמה, גם מתודת בנאי ניתן להעמיס, חוקי העמסת הבנאי זהים לחוקים של העמסת מתודות (Method Overloading) שנסקרו בעבר.
 
לסיכום, כללים להגדרת בנאים:
  • שם הבנאי זהה לשם המחלקה.
  • לא ניתן להגדיר במפורש ערך מוחזר, אולם הבנאי מחזיר את הכתובת של האובייקט שזה עתה נוצר.
  • למחלקות מוגדר בנאי ברירת מחדל (Default Constructor) אשר אינו מקבל פרמטרים ותפקידו לאתחל את משתני המחלקה (איפוס).
  • ניתן, ואף רצוי להעמיס את הבנאים.
  • בנאי יכול להיות פרטי (Private) או ציבורי (Public), אולם בבנאי פרטי נשתמש במקרים מיוחדים בלבד (אחד שכזה יוצג בהמשך הספר).

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

 
class ClassName
{
public ClassName():this(Type1 var1)
{
. . .
}
public ClassName(Type1 var1)
{
. . .
}
}

לדוגמה (InitListSample):
 1  : class Person 
 2  : { 
 3  :     private string LastName; 
 4  :     private string FirstName; 
 5  :     private float SalaryPerHour; 
 6  :     private float WorkingHours; 
 7  :     public Person() 
 8  :         : this("--------", "--------") 
 9  :     { 
 10 :         Console.WriteLine("First Ctor"); 
 11 :     } 
 12 :     public Person(string ln, string fn) 
 13 :         : this(ln, fn, -1, -1) 
 14 :     { 
 15 :         Console.WriteLine("Second Ctor"); 
 16 :         LastName = ln; 
 17 :         FirstName = fn; 
 18 :     } 
 19 :     public Person(string ln, string fn, float sal, float hours) 
 20 :     { 
 21 :         Console.WriteLine("Third Ctor"); 
 22 :         LastName = ln; 
 23 :         FirstName = fn; 
 24 :         SalaryPerHour = sal; 
 25 :         WorkingHours = hours; 
 26 :     } 
 27 :      . . . 
 28 : } 

כאשר מופעל הבנאי הראשון (בשורה 7) הוא קורא לבנאי השני (שורה 12) שמקבל שני פרמטרים, הבנאי השני קורא בשורה 13 לבנאי השלישי (זה שמקבל ארבעה פרמטרים), לאחר שהבנאי השלישי מתבצע הבנאי השני ורק לאחריו מתבצע הבנאי הראשון.
 1  : class Program 
 2  : { 
 3  :     static void Main(string[] args) 
 4  :     { 
 5  :         Person e1 = new Person(); 
 6  :         Person e2 = new Person("Moshe", "Stamshem"); 
 7  :         e2.Print(); 
 8  :  
 9  :     } 
 10 : } 
פלט:
 
 
פלט של דוגמת הקוד InitListSample
 
 


כל הזכויות שמורות למחבר ©