בפיתוח תוכנה עסקית זכתה מתודולוגיה זו לתפוצה רחבה החל מסוף שנות ה־80 של המאה ה-20, תחילה ב־Smalltalk ולאחר מכן בשפות התכנות C++‎ וטורבו פסקל. שפת אייפל שהוכרזה ב־1985 הושפעה מהשפות פסקל, Simula, Ada, Z ושימשה השראה לשפות פופולריות כמו #C ,Java ,ו־Ruby.
שפות נוספות התומכות בתכנות מונחה־עצמים הן פייתון, Ruby ,Delphi ועוד רבות אחרות.
במסגרת יוזמת NET. של חברת מיקרוסופט פיתחה החברה שפה חדשה לתכנות מונחה־עצמים, #C, והשלימה יכולת זו שהייתה חלקית בגרסה שישית של שפת Visual Basic, בגרסה הקרויה Visual Basic .NET.
מהות הפרדיגמה וטרמינולוגיה.
מרכיב בסיסי בתכנות מונחה־עצמים הוא המחלקה (Class). מחלקה היא מבנה מופשט בעל שדות (fields) המגדירים את המחלקה כלפי פנים, תכונות (Properties) המגדירות ומאפיינות את המחלקה כלפי חוץ, ושיטות (Methods) שהן פונקציות ייחודיות למחלקה, הפועלות על משתני המחלקה. בחלק משפות התכנות (בעיקר המודרניות כמו Java ו־#C) קיימים גם אירועים (Events), שהם הודעות השייכות למחלקה ומוזנקות בהקשרים שונים, למשל בתחילתו או בסיומו של הליך או כתגובה לקלט מהמשתמש.
על מנת להשתמש במחלקה, המתכנת יוצר מופעים שלה. כל מופע של מחלקה הוא עצם (Object או Instance). היחס בין המחלקה לבין המופע, הוא היחס בין הגדרת טיפוס (Type) לבין הכרזת משתנה מסוג טיפוס בפועל בזיכרון המחשב. כלומר, בעוד שהמחלקה מהווה תבנית ומגדירה את התכונות והפעולות השייכות לה, עצם הוא משתנה פעיל שטיפוסו הוא המחלקה ומכיל את המידע הזה בפועל - כל עצם מכיל את התכונות והפעולות שהוגדרו במחלקה ממנה נוצר. לדוגמה, למחלקה הקרויה "מכונית" יש תכונות: צבע, דגם, שנת יצור, ופעולות: התנעה, נסיעה, עצירה. כל מכונית מסוימת היא עצם במחלקה זו, ולכל תכונה ערך המתאים למכונית המסוימת, למשל מזדה לבנה מודל 2003.
בכל מחלקה קיימות שתי פונקציות שמופעלות באופן אוטומטי על המופעים שלה בעת יצירתם ובעת מחיקתם. בעת יצירת המופע תופעל פונקציית בנאי (Constructor), באמצעותה אפשר לאתחל את האובייקט, לעיתים באמצעות פרמטרים המועברים אליה. בעת הריסת האובייקט תופעל פונקציה הורסת (Destructor), באמצעותה אפשר למשל לשחרר זיכרון שהיה בשימוש על ידי העצם, או למחוק אובייקטים אחרים שכבר אין בהם צורך. בשפות המשתמשות במנגנון איסוף זבל (Garbage collection), כגון Java, ישנה פונקציה מקבילה אך היא נקראת רק בעת ההריסה הסופית של העצם על ידי המנגנון, ולכן תפקידיה שונים.
התכנות במתודולוגיה זו מצריך תכנון ומאמץ יתר מבשיטה הרגילה, מפני שצריך לנתח, להגדיר ולארגן מראש את המערכת כולה ולבנות את כל המודל שלה, שבו יוגדרו כל האובייקטים השונים, הפונקציונליות שלהם וההיררכיה שביניהם, כך שהמתכנת הופך להיות ארכיטקט וקבלן גם יחד. הכתיבה אינה אינטואיטיבית כמו בשפה פרוצדורלית מכיוון שאפילו כתיבת פונקציה פשוטה, כופה יצירת אובייקט שלם עם פונקציות בונות והורסות. מצד שני נוצרת תוכנה מאורגנת, ולמתכנת המשתמש באובייקטים או המנסה לתחזק אותם, הרבה יותר קל להתמצא, לפתח ולתחזק כאשר הוא מתבסס על קוד של תכנות מונחה־עצמים, בהשוואה לקוד פרוצדורלי, מפני שהוא מאורגן וממופה יותר, ושינוי קטן במקום אחד בתוכנה אמור להשפיע באופן מקומי על האובייקט שבו הוא התבצע השינוי, ולא על כל התוכנה כולה.
מאפיינים.
אין הסכמה כללית לגבי סט מסוים של תכונות המגדירות מהו תכנות מונחה־עצמים, או מהי שפה מונחית־עצמים. חוקרים שונים מגדירים מאפיינים שונים, ושפות שונות תומכות במאפיינים שונים. כאשר כל מאפיין בנפרד מופיע גם בפרדיגמות תכנות אחרות:
מאפיינים נוספים הם: זהות (Identity) - דרך לבדוק האם שני אובייקטים הם בעצם אותו אובייקט, והימשכות (סריאליזציה) - שהיא היכולת לשמור על מצב העצם לאורך זמן, למשל לאחר כיבוי והדלקת המחשב.
הפשטת נתונים.
בתכנות מונחה עצמים המתכנת יוצר מחלקות שמשמשות כעין "שחקנים" מופשטים, שיכולים לבצע עבודה, לדווח על מצבם ולתקשר עם אובייקטים אחרים. בשיטה זו ניתן לבצע הכללה של מקרים פרטיים. באמצעות שימוש בכימוס ניתן לבצע פולימורפיזם.
בדוגמה הבאה בשפת ג'אווה, נעשית הדגמה בהגדרה מופשטת מחלקת בעל חיים Animal, שיש לה את התכונות "מיקום", ו"מאגרי אנרגיה", ואת השיטות: "האם רעב", "לאכול", ו"לנוע".
public class Animal extends LivingThing
private Location loc;
private double energyReserves;
public boolean isHungry() {
return energyReserves &lt; 2.5;
public void eat(Food food) {
// Consume food
energyReserves += food.getCalories();
public void moveTo(Location location) {
// Move to new location
this.loc = location;
באמצעות ההגדרה שלמעלה של חיה ניתן ליצור אובייקטים כמו חזיר ופרה ולקרוא להן באופן הבא:
thePig = new Animal();
theCow = new Animal();
if (thePig.isHungry()) {
thePig.eat(tableScraps);
if (theCow.isHungry()) {
theCow.eat(grass);
theCow.moveTo(theBarn);
בדוגמה לעיל, המחלקה Animal היא הפשטה במקום מין של חיה בפועל, LivingThing היא הפשטה נוספת (במקרה זה הכללה) של Animal. ניתן לראות שבאמצעות הגדרה מופשטת של הטיפוס הכללי ניתן לבצע הכללה, ולהשתמש בה למספר רב של פרטי חיות, במקום לכתוב קוד נפרד לכל בעל חיים, דבר שמאפשר ליצור ריכוז של קוד. בנוסף, הפשטה כזו יכולה להסיר את הצורך שמתכנת היישום יעסוק בסוג המזון של כל חיה, ולתת למשתמש לעסוק בנתונים אלו. אם יש מאפיינים נפרדים לכל בעל חיים, למשל פרה שנותנת חלב בזמן שהיא חיה, לעומת חזיר שנותן בשר רק במותו, ניתן לאפיין כל סוג בנפרד באמצעות פולימורפיזם של תת־טיפוס.
כימוס.
המימוש הפנימי של אובייקט הוא באופן כללי מוסתר מחלקי קוד החיצוניים להגדרת האובייקט. רק המתודות של האובייקט עצמו (או לעיתים, של אובייקטים אחרים השייכים לאותה מחלקה) רשאיות לבצע פעולות על השדות שלו.
יצירת האובייקט כמודול סגור וכ"קופסה שחורה", בה כל המכניזם הפנימי עלום וכמוס מפני המשתמש, מאפשרת בקרה טובה על כל הפעילות עם האובייקט. כל הנתונים הפנימיים כמו גם פעולות פנימיות, המשמשים את העצם, אינם ידועים מחוץ לעצם (כלומר למתכנת המשתמש בו) ולכן מפתח האובייקט יכול לשנותם בחופשיות מבלי שיהיה צורך לשנות את התוכנות אשר משתמשות באובייקט. הדבר גם מאפשר להחליף בקלות ופשטות מנועי תכנות אשר פועלים מבחינה פנימית באופן שונה לגמרי, כל זמן שהם נותנים כלפי חוץ את אותם שיטות ומאפיינים. קשר מסוג זה בין עצמים קרוי צימוד רפוי (loose coupling), והוא מקל על יצירת תוכנית מודולרית, פשוטה להבנה וניווט, וקלה לתחזוקה. ניתן לתאר כלי רכב שמשתמש במנוע מסוים ויש לו מעט חיבורים סטנדרטיים, ללא כל גישה לפעילות הפנימית של המנוע. הסיכוי שהפעילות של כלי הרכב באמצעות המנוע לגרום לו לתקלה פנימית מתמעט, והאפשרות להחליף מנוע מטיפוס אחד במנוע עם ממשקים חיצוניים דומים אפשרי מאוד. בדוגמה ניתן לראות כלי רכב, שמשתמש במנוע, תיבת הילוכים ומשאבת דלק, כאשר כל אחד מהם הוא אובייקט כמוס, שלא ניתן לשנות את החלקים הפנימיים שלו אלא להשתמש בשיטות שהוא חושף.
class Vehicle
Engin engine = new Engin();
Gear gear = new Gear();
GasPump gasPump = new GasPump();
Handbrake handbrake = new Handbrake();
public void StartDriving(int gearNum)
engine.TurnOn();
gear.TransferGear(gearNum);
handbrake.SetStatus(false);
gasPump.FuelInject(20.55F);
טיפוסי נתונים מופשטים מאפשרים כימוס בצורה דומה לזאת של אובייקטים.
ישנן שפות תכנות מונחות־עצמים שאינן מאפשרות כימוס, או מאפשרות להפר אותו:
תת־טיפוסים.
הטיפוס של אובייקט הוא הממשק שלו. כלומר, אוסף ההודעות שהוא יודע לקבל, או אוסף המתודות הציבוריות שלו. המבנה הפנימי של האובייקט אינו חלק מהטיפוס שלו, כיוון שאינו משפיע על אוסף הפעולות שניתן לבצע איתו.
אם אובייקט יכול לבצע קבוצה של פעולות, הוא שייך גם לכל טיפוס שדורש רק חלק מהפעולות האלה. היכולת להתעלם מחלק מהממשק של אובייקט מאפשר לכתוב קטע קוד יחיד המאפשר לבצע מניפולציה על מגוון רחב של אובייקטים, תוך שהוא דורש רק את הממשק המשותף שלהם. תכונה זו מנוצלת במיוחד בשפות בעלת טיפוסיות ברווז כגון פייתון, Ruby, ו־Smalltalk. ממשקים (Interface) בשפת ג'אווה ומחלקות אבסטרקטיות בשפת ++C מאפשרים גם הם להגדיר במפורש תתי־טיפוסים, בלי צורך לבצע ירושה (ראו בהמשך) של המימוש.
ישנן שפות שאינן מונחות־עצמים התומכות בתתי טיפוסים - למשל שפת ML המאפשרת להעביר לפונקציה רשומה כלשהי, כל עוד היא מכילה לפחות את השדות שהפונקציה דורשת - גם אם היא מכילה שדות נוספים, וגם אם לא.
תמיכה לתת־טיפוסים בשפה מסייעת בשימוש בפולימורפיזם.
ירושה.
אובייקטים המשתפים חלקים מהממשק שלהם, משתפים לעיתים קרובות גם התנהגות. ירושה מאפשרת לממש את ההתנהגות המשותפת הזאת פעם אחת. רוב השפות מונחות־העצמים משיגות את היכולת הזאת דרך מחלקות, שכל האובייקטים הנוצרים דרכן משתפים התנהגות - ודרך מנגנון שנקרא ירושה, המאפשר למחלקה אחת להרחיב מחלקה אחרת - להוסיף לה מימוש והתנהגות דרך מימושים של מתודות חדשות, הוספה של משתנים, ובמקרה הצורך ביצוע של דריסה של מתודות שהוגדרו במחלקה ממנה יורשים. (שפות אחרות משתמשות במנגנון שונה, הנקרא delegation).