מחלקה היא תוכנית אב
עד עכשיו הקוד שלכם חי במתודות שמעבירות ערכים פשוטים. מחלקה מאפשרת לאגד נתונים קשורים ואת ההתנהגות שפועלת עליהם לטיפוס אחד עם שם. המחלקה היא תוכנית האב; הדברים שעובדים איתם בפועל הם אובייקטים שנוצרים ממנה.
מחלקה מצהירה על שני סוגי חברים: שדות (הנתונים שכל אובייקט מחזיק) ומתודות (מה שכל אובייקט יכול לעשות).
new Dog() בונה אובייקט בזיכרון ומחזיר לכם הפניה אליו. d.name ו-d.bark() ניגשים לאובייקט הספציפי הזה.
לכל אובייקט יש מצב משלו
כל הטעם במחלקה הוא שאפשר לייצר ממנה אובייקטים עצמאיים רבים, שכל אחד נושא ערכי שדות משלו. שינוי של אחד אף פעם לא נוגע באחר.
rex ו-bella הם שני אובייקטים נפרדים. לכל אחד יש name משלו, ולכן כל bark() מדפיס ערך אחר. הנתונים האלה, ששייכים לכל אובייקט בנפרד, נקראים מצב מופע (instance state).
שדות ומתודות עובדים יחד
מתודות בתוך מחלקה יכולות לקרוא ולעדכן ישירות את השדות של האובייקט עצמו, בלי צורך להעביר אותם כפרמטרים. המתודה כבר "חיה על" האובייקט שאת הנתונים שלו היא משנה.
שימו לב ש-increment() לא מקבלת ארגומנטים. היא פועלת על השדה ששייך ל-Counter שעליו קראתם לה. זה ההבדל בין מתודה של מחלקה לבין מתודה סטטית עצמאית: למתודה יש אובייקט מובלע לפעול עליו.
מילת המפתח this
בתוך מתודה, this הוא הפניה לאובייקט שעליו נקראה המתודה. בדרך כלל לא צריך אותו: כתיבת count כבר אומרת this.count. אבל this הופך להכרחי כששם של פרמטר מתנגש עם שם של שדה, מה שקורה כל הזמן ב-setters ובבנאים.
טעות נפוצה של מתחילים היא לכתוב x = x; בתוך move. זה רק משים את הפרמטר לעצמו ומשאיר את השדה בלי שינוי: הקומפיילר לא יזהיר אתכם, והאובייקט ישמור בשקט את הערכים הישנים. this.x = x; הוא מה שבאמת מעדכן את השדה.
ערכי ברירת מחדל של שדות והפניות null
כשיוצרים אובייקט, השדות שלו לא נשארים עם זבל: Java מאתחלת אותם לערכי ברירת מחדל: 0 למספרים, false ל-boolean, ו-null להפניות לאובייקטים כמו String. ברירת המחדל null הזו היא המקור של קריסה קלאסית.
u.name הוא null כי אף אחד לא הגדיר אותו, ולכן קריאה ל-.length() עליו זורקת NullPointerException. תמיד השימו ערכים משמעותיים לאובייקט לפני שמשתמשים בשדות שלו, וזו בדיוק הבעיה שבנאים פותרים.
ארגון הקוד סביב מחלקות
תוכניות אמיתיות ממדלות את התחום שלהן כמחלקות שמחזיקות נתונים ואת הפעולות עליהם יחד. כאן מחלקה אחת, BankAccount, שומרת יתרה ושומרת על האופן שבו היא משתנה:
הנתונים (balance) והכללים לשינוי שלהם (deposit, withdraw) נמצאים במקום אחד. קוד במקומות אחרים מבקש מהחשבון לעשות דברים במקום לשנות את המספרים שלו ישירות: זה הבסיס לעיצוב נקי שקל לתחזק.
הבא בתור: בנאים
הגדרה ידנית של כל שדה אחרי new מייגעת וקל לשכוח אותה, וכפי שראיתם עכשיו, שדה שנשכח משאיר null שמחכה לקרוס. בנאי (constructor) מאפשר לדרוש ולאתחל את השדות של אובייקט ברגע שהוא נוצר, כך ש-BankAccount לעולם לא יכול להתקיים בלי בעלים. זה העמוד הבא.
שאלות נפוצות
מה זו מחלקה ב-Java?
מחלקה היא תוכנית אב שמגדירה את הנתונים (שדות) ואת ההתנהגות (מתודות) שיהיו לסוג מסוים של אובייקט. המחלקה עצמה היא רק תבנית: יוצרים ממנה אובייקטים אמיתיים עם new. למשל, מחלקה Dog מתארת שלכל כלב יש name והוא יכול לעשות bark(), וכל new Dog() הוא כלב נפרד עם שם משלו.
מה ההבדל בין מחלקה לאובייקט ב-Java?
מחלקה היא ההגדרה; אובייקט הוא מופע קונקרטי שנבנה מההגדרה הזו עם new. מחלקה Person אחת יכולה לייצר אובייקטי Person רבים, וכל אחד מחזיק ערכי שדות משלו. חשבו על המחלקה כעל תבנית עוגיות ועל האובייקטים כעל העוגיות עצמן: שינוי השדות של אובייקט אחד אף פעם לא משפיע על אובייקט אחר.
מה עושה מילת המפתח this במחלקה ב-Java?
this מתייחס לאובייקט הנוכחי: המופע הספציפי שהמתודה שלו רצה. משתמשים בו כדי להגיע לשדות של האובייקט עצמו, במיוחד כשלפרמטר יש אותו שם כמו לשדה (this.name = name;). בלי this, ההשמה פשוט הייתה משימה את הפרמטר לעצמו, והשדה היה נשאר ללא שינוי.