מאמר ראשון בסדרת מאמרים בנושא תכנות מונחה עצמים המביא להיכרות עם מושג המחלקות
Convert to study guideBETA
Transform any presentation into a summarized study guide, highlighting the most important points and key insights.
1 of 3
Download to read offline
More Related Content
תכנות מונחה עצמים - מחלקות
1. מחלקות – Classes
אנו עוסקים בפיתוח על רעיון המבנים ( )Structuresב – .C
נבחין בהגדרת משתנה מסוג intלדוגמה: 01= ,int xכאן אנו עושים שימוש בטיפוס נתונים שמוגדר מראש והאובייקט
נבנה במחסנית, אנו נעשה הבחנה בין אובייקטים שנבנים במחסנית לבין אובייקטים שנבנים בערימה היות וקיימים
הבדלים משמעותיים הן בדרכי הגישה והן בעלות וזמני הגישה אל אובייקטים אלו.
בחזרה למחלקות.
ניתן להתבונן במחלקות כבתרשים אפיון עבור אובייקטים שאנו רוצים לבנות בזיכרון.
בניגוד ל – ... string ,double ,intוכד', שהם טיפוסים מוגדרים מראש, מחלקה היא טיפוס נתונים שאנו בונים בעצמנו ועל
כן, הוא יכיל מאפיינים ותכונות שאנו נעניק לו.
נניח ונרצה ליצור מחלקה של רובוטים. כאן יש מקום לדבר על המושג .Encapsulationהרעיון שעומד מאחורי
אנקפסולציה הוא שילוב בין מהו האובייקט לבין מה הוא עושה.
לכל מחלקה יש משתנים – modifiersמסוגים שונים. משתנים אלו יכולים להיות ציבוריים – ,publicפרטיים - private
ועוד.
כמו כן, לכל מחלקה יש בנאי והורס. אותו הבנאי הוא פונקציה מיוחדת שנכתבה בצורה מאוד מסוימת: שם המחלקה
שאובייקטים מהסוג שלה היא בונה ללא ערך החזרה. כלומר, אם החלטנו לבנות מחלקה של רובוטים – ,Robotsאז הבנאי
של המחלקה ייקרא )( .Robotsהורס של המחלקה ייקרא באופן זהה לבנאי רק עם ∾ לפני השם שלו כך: )(.∾Robots
ככל אצבע, באופן עקרוני וכללי; הבנאי, ההורס ופונקציות אחרות יהיו תחת הכותרת publicומשתנים יהיו תחת הכותרת
:
:.private
הבנאי נקרא בכל פעם שיוצרים אובייקט ממחלקה מסוימת וגם אם אינו מוגדר מראש על ידנו, ייווצר בנאי והורס
ו
דפולטיביים. אם נחזור למחלקת הרובוטים שלנו נוכל לסכם מה שעשינו עד כה:
{ Class Robots
:Public
} ;"Robots () { cout << "Building a Robot
} ;"∾Robots () { cout << "Destroying a Robot
2. כעת, כמו שאמרנו, מחלקה היא לא אחרת מאשר סכימה של האובייקט שברצוננו ליצור ועל כן, בהמשך לדוגמה שלנו,
נשאל את עצמנו אילו פונקציות האובייקט שלנו מבצע.
נניח והרובוט שלנו יודע לבצע 2 פעולות בלבד: לחשב ולאכול. פעולות אלו, המכונות ,Member Methodsיהיו ציבוריות
ותתאפשר אליהן גישה מחוץ למחלקה. כאן הגדרנו את מה שהאובייקט שלנו עושה.
כמובן, שאין מניעה להמשיך ולאפיין את האובייקט שלנו כאשר כל המאפיינים שלו ציבוריים, כלומר, מבחינה תחבירית,
אין שום מניעה לעשות כך, אך זהו המקום לציין שיש חשיבות גדולה לבצע את ההפרדה שהוזכרה קודם בדבר ציבוריות
ופרטיות של מאפיינים.
אם בכל זאת נגדיר הכול כציבורי, אנו נפספס אלמנט חשוב ביותר– מיסוך.
נסביר: ++ Cמאפשרת לנו להגדיר אלמנטים מסוימים כפרטיים ובכך לחסום את אפשרות הגישה הישירה אליהם מחוץ
למחלקה, כך שניתן יהיה לגשת אליהם אך ורק דרך פונקציות ציבוריות. כל פונקציה ציבורית תוגדר באיזה אופן היא
ניגשת לנתונים וכיצד היא משנה אותם, כך שאנו יכולים להיות סמוכים ובטוחים ש"כל צופה שילם על כרטיס כדי לצפות
במופע" (בהקבלה כמובן).
כעת נדבר על הגדרת הפרטיים: כאן נגדיר את מה שהאובייקט שלנו הוא.
בחזרה לדוגמא שלנו, נגדיר, כי לרובוט שלנו התכונות היסודיות הבאות: שם, חוכמה והאם הוא מאושר. כל אחת
מהתכונות הללו תהא מוגנת משינוי באופן ישיר, ותתאפשר אליהן גישה אך ורק דרך פונקציות תיווך ציבוריות שיוגדרו
מראש.
אין משמעות לשם של פונקציות אלו, אך לשם הסדר הטוב ומתוך מוסכמה קיימת בתחום, נשתמש ברישא Setעל מנת
לשנות ערך של משתנה וברישא Getעל מנת לאחזר ערך של משתנה.
פונקציות אלו, המכונות ,Accessor Methodsיוגדרו בהתאמה עבור התכונות אותן הן מגדירות או שעבורן הן מאחזרות
מידע, כך שבדוגמה שלנו למשל, אם המשתנה Nameהוא מסוג ,stringכך גם פונקציות התיווך שלו יוגדרו: על מנת
לאחזר את ערכו של המשתנה Nameנבנה פונקצית תיווך שמחזירה ,stringועל מנת להציב ערך במשתנה Nameנבנה
פונקצית תיווך מסוג stringהמבצעת השמה. ובאופן כללי: .private member = public value
נשים לב לעובדה שאת כל הפעולות על המשתנים הפרטיים אנו נאלצים לבצע על ידי פונקציות התיווך, כל עוד שאנו
נמצאים מחוץ לגבולות המחלקה (פונקצית mainוכדומה), אך כל עוד שאנו נמצאים בתוך המחלקה, אין מניעה לגשת
למשתנים באופן ישיר ולשנותם.
3. כמו כן, נזכור שככל שנוגע לגישה לאובייקט שנוצר, אנו יכולים להתייחס אליו כשם שנתייחס למבנה רגיל: כאשר אנו
יוצרים את האובייקט במחסנית, הגישה אליו תהיה באמצעות "." וכאשר אנו יוצרים אותו בערימה הגישה אליו תהיה
באמצעות ">-". על הגדרת אובייקטים במחסנית ובערימה – מיד.
יצירה של אובייקטים מטיפוס המחלקה שהגדרנו תתבצע באופן זהה ליצירת אובייקטים מטיפוסים השמורים כגון
... int, doubleכך שאם בדוגמא שלנו יצרנו מחלקה שנקראת ,Robotאז יצירת רובוט בשם 2 r2dבמחסנית תהיה
;2.Robot r2d
כעת, נגדיר את שם הרובוט באמצעות פונקצית התיווך r2d2.SetName ("R2D2"); :SetName
נשים לב שהגישה היא דרך האובייקט עצמו ולא דרך המחלקה ( r2d2.Setולא .)Robot.Set
כדי לקבל את רמת החוכמה של 2 , R2Dאנו ניגש באמצעות פונקצית התיווך כך:
;)(.r2d2.GetSmartLevel
כעת, נבנה פונקציה שמציגה לנו את מכלול הנתונים לגבי רובוט מסוים. על מנת לבצע זאת, נבחין בתכונה שציינו קודם
לכן: היות והפונקציה נבנית בגבולות המחלקה, אין לנו צורך בפונקציית התיווך, ואנו יכולים לגשת באופן ישיר לכל
משתנה פרטי כאילו היה ציבורי וכמובן שזאת מבלי לסתור את האמור עד כה, שהרי כל עוד שאנו בגבולות המחלקה, אין
שום מניעה מאיתנו לגשת למשתנים. המניעה באה על מנת לא לאפשר גישה שכזו מבחוץ. ועל כן, פונקציה שכזו תיראה
כך: } ;GetToKnowRobot() { cout << Name << " " << SmartLevel << " " << IsHappy
ואז: ;)(r2d2.getToKnowRobot
היות ואובייקטים ממחלקות מסוימות יכולים להיות "כבדים" והזזתם ממקום למקום דרך המחסנית עלולה לעלות מחיר
כבד של פעולות מעבד וזיכרון, אנו נעדיף לבצע את העבודה דרך הערימה.
נשים לב שמדובר בעבודה עם מצביעים ולכן אנו נצטרך להיזהר ממצבים בהם האובייקט יהיה בזיכרון ויצרוך משאבים, אך
אנו נאבד גישה אליו.
ביצירת אובייקט בערימה, אנו נרגיש בשני שינויים עיקריים בהתנהלות שלנו: היצירה תתבצע באופן הבא:
;)( Robot * OptimusPrime = new Robot
;)"OptimusPrime -> SetName("Optimus Prime והגישה אליו תתבצע באופן הבא: