→ חזרו אחורה

פרק 9 - מבוא למחלקות ועצמים

⏱ 16 דקות קריאה

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

1. מחלקה היא תבנית, אובייקט הוא מופע

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

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

2. בניית מחלקה עם שדות

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

Java

public class Student {
    String name;
    int age;
}
            

זו מחלקה שלמה, שמתארת שכל תלמיד יש לו name (שם) ו-age (גיל). היא נכתבת בקובץ נפרד, למשל Student.java.

3. בנאי (Constructor)

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

Java

public class Student {
    String name;
    int age;

    public Student(String studentName, int studentAge) {
        name = studentName;
        age = studentAge;
    }
}
            

לבנאי אין סוג החזרה (לא void ולא שום דבר אחר) - הוא תמיד נקרא בדיוק כמו המחלקה.

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

הבנאי קובע את ה"מצב" (state) ההתחלתי של האובייקט: כל אובייקט חדש מקבל עותק עצמאי משלו של השדות - קריאה ל-new Student("דנה", 17) ואז ל- new Student("יוסי", 16) יוצרת שני אובייקטים נפרדים לגמרי, שכל אחד "זוכר" רק את הערכים שהועברו לבנאי שלו. שינוי שדה באובייקט אחד לא משפיע בכלל על האובייקט השני.

4. יצירת אובייקט ושימוש בו

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

Java

Student s1 = new Student("דנה", 17);
Student s2 = new Student("יוסי", 16);

System.out.println(s1.name + " בת " + s1.age);
System.out.println(s2.name + " בן " + s2.age);
            

Student - סוג המשתנה: אובייקט מסוג תלמיד.

s1, s2 - שני אובייקטים נפרדים לגמרי, כל אחד עם שם וגיל משלו.

s1.name - גישה לשדה name של האובייקט הספציפי s1.

5. הוספת מתודה למחלקה

מחלקה יכולה להכיל גם מתודות (בדיוק כמו שלמדנו בפרק המתודות), שיכולות להשתמש בשדות של האובייקט:

Java

public class Student {
    String name;
    int age;

    public Student(String studentName, int studentAge) {
        name = studentName;
        age = studentAge;
    }

    boolean isAdult() {
        return age >= 18;
    }
}
            

עכשיו אפשר לקרוא למתודה על כל אובייקט בנפרד, בדיוק כמו לשדה:

Java

Student s1 = new Student("דנה", 17);
System.out.println(s1.isAdult());
            
מבט קדימה: בהמשך הדרך תפגשו גם ירושה (Inheritance) - יכולת ליצור מחלקה חדשה שמבוססת על מחלקה קיימת ומרחיבה אותה. זה נושא מתקדם יותר שבנוי בדיוק על מה שלמדנו כאן.

6. טעויות נפוצות

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

סוג החזרה בבנאי: בנאי אף פעם לא כותבים לו סוג החזרה, אפילו לא void.

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

🎓 זווית הבגרות

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

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

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

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

7. תרגול

מה יודפס למסך על ידי הקוד הבא?

Java
Student s1 = new Student("דנה", 17);
Student s2 = new Student("יוסי", 19);
System.out.println(s1.isAdult() + " " + s2.isAdult());

מה יודפס למסך על ידי הקוד הבא? (השוואה בין השדות של שני אובייקטים)

Java
Student s1 = new Student("דנה", 17);
Student s2 = new Student("יוסי", 16);
System.out.println(s1.age > s2.age);

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

כתבו שורת קוד שיוצרת אובייקט חדש מסוג Student בשם s1, עם השם "רון" וגיל 15.

כתבו קוד שמדפיס את השדה name של האובייקט s1.

פרק 8 - מערך דו-ממדי פרק 10 - רקורסיה