בניית מחלקות
מבנה מחלקה בסיסי
public class Student
{
// תכונות
private string name;
// פעולות
public string GetName()
{
return name;
}
}
תכונות לעומת משתנים
- משתנה – קיים רק בזמן ריצה של פעולה
- תכונה – חלק מהעצם, כל עוד הוא קיים
הרשאות גישה
| הרשאה | משמעות |
|---|---|
| private | נגיש רק בתוך המחלקה |
| public | נגיש מכל מקום |
Constructor: פעולה בונה
הפעולה הבונה:
- מופעלת פעם אחת בלבד
- מאתחלת את תכונות העצם
- אין לה טיפוס חזרה
public Student(string n, string id)
{
name = n;
idNum = id;
}
בדרך כלל נלמד זאת כך:
public Student(string name, string id)
{
this.name = name; // הוא העצם שלנו this
this.id = id; // הכרחי כאשר הפרמטר זהה לתכונה this
}
יצירת עצם – new
Student s1 = new Student("Dana", "123");
// ואז יש קריאה לפעולה בונה new כדי לבנות את העצם משתמשים במילה
שלבי הבנייה:
- הקצאת זיכרון
- אתחול תכונות
- החזרת העצם החדש
public class Student
{
// תכונות
private string name;
// פעולות
public string GetName()
{
return name;
}
}
המחלקה המלאה כמעט כפי שהוצגה בשיעור
public class Student
{
private int id;
private string name;
private int age;
public Student()
{
}
// //פעולה בונה מעתיקה
public Student(Student other)
{
this.id = other.id;
name = other.name;
age = other.age;
}
public Student(int ageee, string nameeee)
: this(ageee, nameeee, 110)
{
Console.WriteLine("Invented ID");
}
public Student(int age, string name, int id = 110)
{
this.age = age;
this.name = name;
this.id = id;
}
public int GetAge()
{
return age;
}
public void SetAge(int value)
{
age = value;
}
public string GetName()
{
return name;
}
public void SetName(string value)
{
name = value;
}
public int GetId()
{
return id;
}
public void SetId(int value)
{
id = value;
}
public void AddOneYear()
{
age++;
}
}
עבודה עם עצמים
עבודה עם עצמים
כדי להשתמש בעצם:
- מגדירים משתנה מטיפוס המחלקה
- בונים עצם עם
new- מפעילים פעולות
דוגמה מלאה
Student s = new Student("Noam", "456");
s.SetMath(90);
Console.WriteLine(s.ComputeAverage());
שלבי כתיבה והמונחים בבחינות
כותרת המחלקה:
public class Student
התכונות:
private string name;
private int id;
private int age;
הבנאי:
public Student(string name, string id)
{
this.name = name; // הוא העצם שלנו this
this.id = id;
}
פעולות קובעות ומאחזרות:
public int GetId()
{
return id;
}
public string GetName() => name; // פונקציה בכתיבה מקוצרת
דגשים משיעור 29/1
- פתיחה: חזרנו על מטרת המחלקה, אבסטרקציה והכמסה (encapsulation); תכונות מוגדרות כ־
privateוגישה מבחוץ רק דרך פעולות. - דוגמת Student: (
GetName,SetName), בהמשך ראינו כתיבה מהירה של כל זה עם הקיצור gs. - בנאים:
newיוצר עצם ומפעיל בנאי; בנאי ברירת־מחדל קיים כשאין בנאים אחרים; ברגע שמגדירים בנאי עם פרמטרים צריך להוסיף גם בנאי ריק אם רוצים לאפשר יצירה בלי פרמטרים. thisושרשור בנאים: הבחנה בין פרמטר לתכונה, ושימוש ב־(...) this :כדי להימנע מכפילות קוד ולהעביר אחריות לבנאי מרכזי (אפשר גם דרך Setters כדי לבצע ולידציה).- פעולה בונה מעתיקה: קבלת עצם מסוג Student והעתקת ערכים ליצירת עצם חדש (לא רק העתקת הפניה), כולל דיון מתי שכפול כן הגיוני.
- סדר כתיבה מומלץ: תכונות ⟵ בנאים ⟵ פעולות מאחזרות/קובעות ⟵ פעולות נוספות.
- שימוש חוזר בקוד: בדוגמת Point במטלה 11y2 הראינו שכדאי לקרוא לפעולה קיימת (
Distance) במקום לחשב מחדש. - שימוש ב־IntelliSense: מקלידים נקודה אחרי שם העצם כדי לגלות פעולות קיימות במחלקה ומה הן עושות.
- פעולה פנימית מול חיצונית: פנימית נמצאת בתוך המחלקה ופועלת על (בתוך) העצם
this; חיצונית נמצאת מחוץ למחלקה ומפעילה את העצם שלפני הנקודה מבחוץ. כלל אצבע לבגרות: חיצוניתpublic static, פנימיתpublicללאstatic(הרחבה עלstaticנדחתה לשיעור הבא). - מעבר לדוגמת Test ו־DateTime: שינוי תאריך עם
AddאוAddDaysמחזיר עצם חדש מטיפוס DateTime. לכן היתה דרושה השמה במשתנהd(שימו לב: זה תלוי מימוש. יכולה להיות פעולה שמשנה תכונות בעצםd. ב־IntelliSense איפשר לנו להבין את כללי המשחק). בנוסף מרגע שביצענו השמה ל-dיש כאן שינוי הפניה. נותק הקשר מהתכונה שבמבחןt2: שינוי ההפניה לא משנה את התכונה בתוך העצםt2ולא מפנה אותה לזכרון החדש אליו הופנהd. אילו הפעולה Add היתה משנה את תוכן העצםdאז התוצאה היתה שונה לגמרי.המחלקה Test כפי שהוצגה בשיעור
public class Program { // פעולה חיצונית public static void Hizonit7() { Student s1 = new Student(); // 0 NO NAME Student s2 = new Student(s1); //משתמש בבונה מעתיקה Student s3 = new Student(5, "Name"); Test t1 = new Test(); Test t2 = new Test(t1.GetTestDate().Add(new TimeSpan(2, 30, 0, 0))); DateTime d = t2.GetTestDate(); // DateTime קריאה לפעולה פנימית המוגדרת במחלקה // d על העצם d = d.AddDays(1); // t2 מוסיף יום. לא משפיע על התאריך בתוך // d ללא השמה גם לא ישפיע על // להפנות d - הפעולה תחזיר עצם חדש ולכן נדרשת ההשמה, שגורמת ל // לכתובת החדשה שהוקצתה בזכרון כאשר נוצר העצם החדש // t2 לא תהיה שום השפעה על תאריך המבחן שיש בתכונה של // כפעולה המחזירה עצם AddDays נובע מהגדרת } } public class Test { private DateTime testDate; public Test() : this(DateTime.Now) { } public Test(DateTime testDate) { this.testDate = testDate; } public DateTime GetTestDate() { return testDate; } public void SetTestDate(DateTime value) { testDate = value; } } - חזרנו שוב על טכניקת הוספת מחלקה קיימת: הוספת מחלקה שהורדה ל־Visual Studio דרך Add > Existing Item.
- Assignment 11y2 — תרגלנו הוספת פעולות פנימיות וחיצוניות.