תכנות מונחה עצמים (Objected oriented programming - OOP)#
טקסט המופיע למטה בסגול מציין קטעים המופיעים בסרטון
ניתן להיעזר בו כדי לחזור על התכנים או לעיין בהם שוב.
סיכום עד כה - תכנות פרוצדורלי#
עד כה עבדנו בגישה פרוצדורלית, שבה יחידות הבסיס של התוכנית הן פונקציות.
כלומר, כתבנו פונקציות שמקבלות נתונים כקלט, מעבדות אותם ומחזירות פלט.
התוכנית נבנית כרצף של קריאות לפונקציות, וכל פונקציה אחראית על חלק קטן מתוך התהליך הכללי.
בגישה הזו קיימת הפרדה ברורה בין הנתונים לבין הפונקציות שמעבדות אותם – הנתונים מאוחסנים במשתנים או במבני נתונים כמו רשימות או מילונים, והפונקציות מקבלות נתונים מטיפוס מסוים ומטפלות בהם.
כלומר, פעולות שמבצעים על הנתונים שלנו ימומשו על-ידי פונקציות, והפונקציות הללו בד”כ לא נוצרות עבור ערכים או משתנים ספציפיים, אלא מוגדרות בצורה כללית.
או במילים אחרות, בתכנות פרוצדורלי ישנן פונקציות כלליות שיכולות לעבוד על מבני נתונים כלליים.
נסביר זאת באמצעות הדוגמא הבאה:
נניח שהיינו בונים מערכת לניהול ציוני סטודנטים.
היינו רוצים פעולות כמו עדכון ציונים (פקטור). בנוסף, אולי היינו רוצים לשמור גם את כתובות הסטודנטים, שמות ותעודות זהות.
איך נממש זאת בתכנות פרוצדורלי?
נאחסן את כל הנתונים (מספרי זהות, שמות, כתובות וציונים) באחד ממבני הנתונים שאנחנו מכירים.
במקרה זה, מתאים להשתמש במילון ונקרא לו לצורך הדוגמא d_grades.
נשים לב שהפעולות שרצינו לעשות, כמו לתת פקטור לציונים, אינן “מובנות” במילון.
על מנת להגדיר פעולות - כמו מתן פקטור - נגדיר פונקציה חדשה בשם update_factor אשר מקבלת את מילון הציונים ומעדכנת אותו.
עם זאת, המערכת שלנו עשויה להתרחב לעוד תחומים - אולי נרצה להוסיף גם מילון לאנשי סגל (שבו יש שם וכתובת, אבל אין ציון).
במצב כזה, הקוד שלנו עשוי להיות מסורבל, ויהיה קשה לעקוב אילו פונקציות מתאימות לכל אחד מהאנשים.
עיצרו וחישבו: איזו פעולה למדנו לעשות על מחרוזת, אך לא ניתן לעשות על שאר הטיפוסים שפגשנו?
כבר ראינו בעבר פונקציות שעובדות רק על חלק ממבני הנתונים - פונקציות מיוחדות לטיפוסים.
במקרה של מחרוזת, קיימות הרבה פעולות הייחודיות רק לטיפוס זה. לדוגמא: lower, upper, strip, split, isalpha, isdigit ועוד.
תכנות מונחה עצמים#
ואם היינו רוצים לשייך פונקציות מסוימות רק לחלק מהאנשים, או בקוד - רק לחלק ממבני הנתונים שברשותנו?
בדיוק כאן נכנס לתמונה הקונספט של תכנות מונחה עצמים.
בתכנות מונחה עצמים, אנו שמים את הנתונים והפעולות בתוך הישות אליה הם שייכים .
כך למשל, כל סטודנט ייוצג כאובייקט עצמאי שמכיל את הציונים שלו ואת הפעולות שאפשר לבצע עליהם.
כלומר, בתכנות מונחה עצמים, יחידת הבסיס כבר איננה הפונקציה, אלא האובייקט, שמאגד בתוכו גם נתונים וגם את הפעולות שניתן לבצע עליהם.
לנתונים שמכיל האובייקט נקרא שדות (Fields), או תכונות (Attributes) שהם בעצם משתנים פנימיים המתארים את מצב האובייקט.
לפעולות המשויכות לאובייקט נקרא מתודות (Methods) או שיטות, שהן פונקציות הקשורות ישירות לאותו אובייקט.
במילים אחרות, הרעיון המרכזי הוא שלא מפרידים עוד בין המידע לבין הפונקציות, אלא מחברים אותם לכדי ישות אחת.
שימו לב
עד כה עבדנו עם אובייקטים שמאגדים בתוכם מתודות ושדות מבלי לשים לב לכך. כאשר השתמשנו ברשימות (list), במילונים (dict) או במחרוזות (str) בעצם יצרנו אובייקטים מהטיפוסים הללו. לכל אובייקט משויכות מתודות שייחודיות עבורו. למשל, לרשימה קיימות מתודות כמו append או sort, למחרוזת יש מתודות כמו upper או split, ולמילון יש מתודות כמו keys או get.
בכל פעם שקראנו לupper על מחרוזת, או append על רשימה, הפעלנו מתודה על אובייקט קיים.
כלומר, עבדנו עם אובייקטים ומתודות עוד מהשלבים הראשונים, ורק כעת אנחנו לומדים כיצד להגדיר מחלקות משלנו ולבנות אובייקטים מותאמים אישית.
הרעיון מאחורי תכנות מונחה עצמים הוא הסתכלות על תוכנה כאוסף של ישויות (או אובייקטים) שיש להם מאפיינים ויכולות לבצע פעולות, ולא כרצף של משימות שיש לבצע.
כלומר, במקום לראות את התוכנית כרשימה של פונקציות או תתי-תוכניות שמופעלות זו אחר זו, אנו רואים אותה כמערכת של ישויות, כאשר בבסיסה כל ישות מורכבת מהנתונים (השדות) ופעולות (המתודות) הייחודיות שלה.
שימו לב שכמו בעולם האמיתי, גם אובייקטים אינם פועלים בבידוד, והם יוצרים ביניהם קשרים ותקשורת, וביחד מייצרים את ההתנהגות הכוללת של המערכת.
אם עד כה ניגשנו לפתור בעיות כרשימה של משימות טכניות שיש לבצע, בתכנות מונחה עצמים ננסה לזהות את הישויות המרכזיות במציאות שאותה המערכת מדמה.
כל ישות במציאות מקבלת ייצוג תכנותי – כאובייקט.
בצורה כזו, האובייקטים עצמם הופכים לשחקנים הראשיים של התוכנית: יש להם מאפיינים שונים, והם יודעים לנהל אותם, כמו גם לבצע פעולות על אובייקטים אחרים (באמצעות מתודות).
הגישה הזו מביאה יתרון גדול מבחינת ארגון, קריאות ותחזוקה של קוד בהרבה סוגי מערכות:
מכיוון שהאובייקטים מקבצים יחד את המידע וההתנהגות שלהם, אפשר להסתכל על כל יחידה באופן מבודד יחסית, בלי לדעת את כל פרטי המימוש של חלקים אחרים במערכת.
בנוסף, ניתן לכתוב תוכנה המדמה באופן ישיר תרחיש מציאותי, משום שהאובייקטים מייצגים ישויות מוכרות.
מחלקות - טיפוסים משלנו#
נחזור כעת לדוגמת הסטודנטים שלנו.
נניח כי נרצה ליצור אובייקטים שייצגו סטודנטים. בכיתה ישנם 100 סטודנטים ולכולם יש שם וכתובת.
לכן, כשנגדיר את היישות של סטודנט, נרצה שיהיו בה שדות המייצגים שם וכתובת.
למרות שלכל סטודנט יהיו אותם שדות - שם וכתובת - השמות והכתובות של הסטונדטים יהיו כמובן שונים.
במילים אחרות, המבנה של הישות יהיה זהה בין הסטודנטים, אבל תוכן, או הערכים של השדות, יהיו שונים.
למעשה, ניתן לחשוב על ייצוג שני סטודנטים שונים כמו על שתי מחרוזות שונות: הטיפוס הוא זהה אך התוכן שונה.
לכן, בתכנות מונחה עצמים נרצה לבנות טיפוס סטודנט, ואת זה ניתן לעשות באמצעות מחלקה או class.
מחלקה למעשה מגדירה טיפוס חדש של אובייקט, כלומר, מגדירה מהם השדות של אובייקט שנוצר ממנה, וכן את המתודות שהאובייקט יוכל להפעיל.
אפשר לראות במחלקה תבנית כללית שעל פיה ניתן לייצר אובייקטים.
מהמחלקה ניתן ליצור מופעים רבים, וכל מופע הוא אובייקט עצמאי בעל ערכים משלו לשדות שהוגדרו במחלקה.
נדגים את התפקיד של מחלקה בתכנות מונחה עצמים, ע”י ייצוג רכב.
במחלקה נוכל להגדיר מאפיינים כמו ארבעה גלגלים, הגה, צבע וצופר, ומתודות כמו לנסוע, לפנות שמאלה, לצפור או לצבוע מחדש.
אך כל רכב, או כל מופע של מחלקת “מכונית” ייראה מעט אחרת: לדוגמא, למכוניות שונות יכול להיות צבע אחר - אך לכל המכוניות יהיה צבע כלשהו, וכל המכוניות יוכלו לפנות שמאלה.
כך, המחלקה משמשת כתבנית אחידה שממנה ניתן לייצר גרסאות רבות של אותו טיפוס אובייקט עם שונות בפרטים.
הבנאי (Constructor)#
המחלקה שהגדרנו למעלה מגדירה את המאפיינים והפעולות שיש לכל רכב, אך לא את הערכים בפועל. למעשה ניתן לחשוב על מחלקה כ”מפעל רכבים”.
אז איך נבנה רכב חדש? או באופן כללי יותר, כיצד יוצרים אובייקט חדש ממחלקה?
בכל מחלקה קיימת מתודה מיוחדת הנקראת בנאי. הבנאי משמש ליצירה ואיתחול ערכי השדות של אובייקט מהמחלקה (או בדוגמא שלנו, ליצירת רכב במפעל הרכבים).
ביחידה הבאה נלמד את התחביר של בניית מחלקה בפייתון, ובפרט - כיצד מגדירים בנאי.