שלום! האם תהיתם פעם מדוע ג'אווה מעוצבת כפי שהיא? במובן שאתה יוצר מחלקות, על בסיסן - אובייקטים, למחלקות יש מתודות וכו'. אבל למה מבנה השפה הוא כזה שתוכניות מורכבות ממחלקות ואובייקטים, ולא ממשהו אחר? מדוע הומצא המושג "חפץ" והוצב בחזית? האם כל השפות עובדות כך ואם לא, אילו יתרונות זה נותן ל-Java? כפי שאתם רואים, יש הרבה שאלות :) בואו ננסה לענות על כל אחת מהן בהרצאה של היום.
קריסטן ניגורד ואולה יוהאן דאל - יוצרי סימולה
נראה שסימולה היא שפה עתיקה בסטנדרטים של תכנות, אבל הקשר ה"משפחתי" שלהם עם ג'אווה גלוי לעין בלתי מזוינת. סביר להניח שאתה יכול לקרוא בקלות את הקוד הכתוב עליו ולהסביר באופן כללי מה הוא עושה :)
עקרונות OOP:
מהו תכנות מונחה עצמים (OOP)
כמובן, ג'אווה מורכבת מאובייקטים ומחלקות מסיבה מסוימת. זו לא גחמה של יוצריה, או אפילו המצאה שלהם. ישנן שפות רבות אחרות המבוססות על אובייקטים. השפה הראשונה כזו נקראה Simula, והיא הומצאה עוד בשנות ה-60 בנורבגיה. בין היתר, סימולה הציגה את המושגים " מחלקה " ו"שיטה " .Begin
Class Rectangle (Width, Height); Real Width, Height;
Begin
Real Area, Perimeter;
Procedure Update;
Begin
Area := Width * Height;
OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
Perimeter := 2*(Width + Height);
OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
End of Update;
Update;
OutText("Rectangle created: "); OutFix(Width,2,6);
OutFix(Height,2,6); OutImage;
End of Rectangle;
Rectangle Class ColouredRectangle (Color); Text Color;
Begin
OutText("ColouredRectangle created, color = "); OutText(Color);
OutImage;
End of ColouredRectangle;
Ref(Rectangle) Cr;
Cr :- New ColouredRectangle(10, 20, "Green");
End;
דוגמה לקוד לקוחה מהמאמר Simula - 50 years of OOP . כפי שאתה יכול לראות, ג'אווה ואבותיו אינם כל כך שונים זה מזה :) זה נובע מהעובדה שהופעתה של סימולה סימנה את לידתו של מושג חדש - תכנות מונחה עצמים. ויקיפדיה נותנת את ההגדרה הבאה של OOP: תכנות מונחה עצמים (OOP) היא מתודולוגיית תכנות המבוססת על ייצוג תוכנית כאוסף של אובייקטים, שכל אחד מהם הוא מופע של מחלקה מסוימת, והמחלקות יוצרות היררכיית ירושה. זה, לדעתי, מאוד מוצלח. לאחרונה התחלת ללמוד ג'אווה, אבל אין בה כמעט מילים שאינן מוכרות לך :) כיום, OOP היא מתודולוגיית התכנות הנפוצה ביותר. מלבד Java, עקרונות OOP משמשים בשפות פופולריות רבות שאולי שמעתם עליהן. אלה הם C++ (משתמשים בו באופן פעיל על ידי מפתחי משחקי מחשב), Objective-C ו-Swift (הם כותבים תוכניות למכשירי אפל), Python (המבוקשים ביותר בלמידת מכונה), PHP (אחת משפות פיתוח האינטרנט הפופולריות ביותר), JavaScript (פשוט יותר לומר מה הם לא עושים בו) ועוד רבים אחרים. למעשה, מה הם ה"עקרונות" האלה של OOP? בואו נספר לכם ביתר פירוט.
עקרונות OOP
זה היסודות. 4 מאפיינים עיקריים היוצרים יחד את פרדיגמת התכנות מונחה העצמים. הבנתם היא המפתח להפוך למתכנת מצליח.עקרון 1. ירושה
החדשות הטובות הן שאתה כבר מכיר כמה מהעקרונות של OOP! :) כבר נתקלנו בירושה כמה פעמים בהרצאות, והספקנו לעבוד עם זה. ירושה הוא מנגנון המאפשר לתאר מחלקה חדשה על סמך מחלקה קיימת (הורה). במקרה זה, המאפיינים והפונקציונליות של מחלקת האב מושאלים על ידי המחלקה החדשה. מדוע נחוצה ירושה ואילו יתרונות היא מספקת? קודם כל, שימוש חוזר בקוד. ניתן להשתמש בשדות ובשיטות המתוארים בכיתות אב במחלקות צאצאות. אם לכל סוגי המכוניות יש 10 שדות נפוצים ו-5 שיטות זהות, אתה רק צריך לשים אותם במחלקת האבAuto
. אתה יכול להשתמש בהם בכיתות צאצאים ללא בעיות. יתרונות מוצקים: הן מבחינה כמותית (פחות קוד) וכתוצאה מכך, מבחינה איכותית (השיעורים הופכים לפשוטים הרבה יותר). יחד עם זאת, מנגנון ההורשה גמיש מאוד, וניתן להוסיף את הפונקציונליות החסרה בצאצאים בנפרד (כמה שדות או התנהגות ספציפית למחלקה מסוימת). באופן כללי, כמו בחיים הרגילים: כולנו דומים להורים שלנו במובנים מסוימים, אבל שונים מהם במובנים מסוימים :)
עקרון 2. הפשטה
זהו עיקרון מאוד פשוט. הפשטה פירושה הדגשת המאפיינים העיקריים והמשמעותיים ביותר של אובייקט ולהיפך - השלכת משניים, חסרי משמעות. בואו לא נמציא את הגלגל מחדש ונזכור דוגמה מהרצאה ישנה על חוגים. נניח שאנחנו יוצרים ארון תיקים של עובדי החברה. כדי ליצור אובייקטים של עובדים, כתבנו מחלקהEmployee
. אילו מאפיינים חשובים לתיאורם בקובץ החברה? שם מלא, תאריך לידה, מספר ת.ז., מספר זיהוי מס. אבל זה לא סביר שאנחנו צריכים את הגובה, העין והשיער שלו בכרטיס מהסוג הזה. החברה אינה זקוקה למידע זה על העובד. לכן, עבור המחלקה Employee
נגדיר את המשתנים String name
, int age
, int socialInsuranceNumber
ו int taxNumber
ונזנוח מידע מיותר עבורנו, כמו צבע עיניים, ונפשט אותו. אבל אם ניצור קטלוג של דוגמניות צילום עבור סוכנות, המצב משתנה באופן דרמטי. לתיאור דוגמנית אופנה חשובים לנו מאוד גובה, צבע עיניים וצבע שיער, אך אין צורך במספר TIN. לכן, במחלקה Model
אנו יוצרים משתנים String height
, String hair
, String eyes
.
עקרון 3: אנקפסולציה
כבר נתקלנו בזה. אנקפסולציה בג'אווה פירושה הגבלת הגישה לנתונים והיכולת לשנות אותם. כפי שאתה יכול לראות, זה מבוסס על המילה "קפסולה". ב"קפסולה" הזו אנחנו מסתירים כמה נתונים חשובים עבורנו שאנחנו לא רוצים שאף אחד ישנה. דוגמה פשוטה מהחיים. יש לך שם פרטי ושם משפחה. כל מי שאתה מכיר מכיר אותם. אבל אין להם גישה לשנות את השם הפרטי והמשפחה שלך. התהליך הזה, אפשר לומר, "מובלע" במשרד הדרכונים: אתה יכול לשנות רק שם פרטי ושם משפחה, ורק אתה יכול לעשות זאת. ל"משתמשים" אחרים יש גישה לקריאה בלבד לשם הפרטי ושם המשפחה שלך :) דוגמה נוספת היא הכסף בדירה שלך. להשאיר אותם לעין באמצע החדר זה לא רעיון טוב. כל "משתמש" (אדם שמגיע אליכם הביתה) יוכל לשנות את מספר הכסף שלכם, כלומר. לאסוף אותם. עדיף לטמון אותם בכספת. רק לך תהיה גישה ורק עם קוד מיוחד. דוגמאות ברורות של אנקפסולציה שכבר עבדת איתם הן משדרי גישה (private
וכו public
') ו-getter-seters. אם שדה age
המחלקה Cat
אינו מובלע, כל אחד יכול לכתוב:
Cat.age = -1000;
ומנגנון האנקפסולציה מאפשר לנו להגן על השדה age
בשיטת קבע, בה נוכל לשים סימון שהגיל לא יכול להיות מספר שלילי.
עקרון 4. פולימורפיזם
פולימורפיזם הוא היכולת להתייחס למספר סוגים כאילו היו אותו סוג. במקרה זה, התנהגותם של אובייקטים תהיה שונה בהתאם לסוג שאליו הם שייכים. נשמע קצת מסובך? בוא נבין את זה עכשיו. ניקח את הדוגמה הפשוטה ביותר - בעלי חיים. בואו ניצור מחלקהAnimal
עם שיטה אחת - voice()
, ושניים מהצאצאים שלה - Cat
ו Dog
.
public class Animal {
public void voice() {
System.out.println("Voice!");
}
}
public class Dog extends Animal {
@Override
public void voice() {
System.out.println("Bow-wow!");
}
}
public class Cat extends Animal {
@Override
public void voice() {
System.out.println("Meow!");
}
}
כעת ננסה ליצור קישור Animal
ולהקצות לו אובייקט Dog
.
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.voice();
}
}
לאיזו שיטה לדעתך ייקרא? Animal.voice()
או Dog.voice()
? שיטת הכיתה תיקרא Dog
: ווף-ווף! יצרנו הפניה Animal
, אבל האובייקט מתנהג כמו Dog
. במידת הצורך, הוא יכול להתנהג כמו חתול, סוס או חיה אחרת. העיקר הוא להקצות התייחסות מסוג כללי Animal
לאובייקט ממעמד צאצא ספציפי. זה הגיוני, כי כל הכלבים הם חיות. לזה התכוונו כשאמרנו "חפצים יתנהגו אחרת בהתאם לסוג שלהם." אם היינו יוצרים אובייקט Cat
-
public static void main(String[] args) {
Animal cat = new Cat();
cat.voice();
}
השיטה voice()
תוציא "מיאו!" מה המשמעות של "היכולת לעבוד עם כמה סוגים כאילו הם אותו סוג"? זה גם די קל. בואו נדמיין שאנחנו יוצרים מספרה לבעלי חיים. המספרה שלנו חייבת להיות מסוגלת לגזור את כל החיות, לכן ניצור שיטה shear()
("גזור") עם פרמטר Animal
- החיה שנחתוך.
public class AnimalBarbershop {
public void shear(Animal animal) {
System.out.println("The haircut is ready!");
}
}
ועכשיו אנחנו יכולים להעביר shear
גם חפצים Cat
וגם חפצים לשיטה Dog
!
public static void main(String[] args) {
Cat cat = new Cat();
Dog dog = new Dog();
AnimalBarbershop barbershop = new AnimalBarbershop();
barbershop.shear(cat);
barbershop.shear(dog);
}
הנה דוגמה ברורה: הכיתה AnimalBarbershop
עובדת עם טיפוסים Cat
כאילו Dog
הם אותו טיפוס. יחד עם זאת, יש להם התנהגות Cat
שונה Dog
: הם משתמשים בקולות שלהם אחרת.
GO TO FULL VERSION