JavaRush /בלוג Java /Random-HE /עקרונות OOP

עקרונות OOP

פורסם בקבוצה
שלום! האם תהיתם פעם מדוע ג'אווה מעוצבת כפי שהיא? במובן שאתה יוצר מחלקות, על בסיסן - אובייקטים, למחלקות יש מתודות וכו'. אבל למה מבנה השפה הוא כזה שתוכניות מורכבות ממחלקות ואובייקטים, ולא ממשהו אחר? מדוע הומצא המושג "חפץ" והוצב בחזית? האם כל השפות עובדות כך ואם לא, אילו יתרונות זה נותן ל-Java? כפי שאתם רואים, יש הרבה שאלות :) בואו ננסה לענות על כל אחת מהן בהרצאה של היום.

עקרונות OOP:

  1. יְרוּשָׁה
  2. הַפשָׁטָה
  3. כימוס
  4. רב צורתיות

מהו תכנות מונחה עצמים (OOP)

כמובן, ג'אווה מורכבת מאובייקטים ומחלקות מסיבה מסוימת. זו לא גחמה של יוצריה, או אפילו המצאה שלהם. ישנן שפות רבות אחרות המבוססות על אובייקטים. השפה הראשונה כזו נקראה Simula, והיא הומצאה עוד בשנות ה-60 בנורבגיה. בין היתר, סימולה הציגה את המושגים " מחלקה " ו"שיטה " . עקרונות של תכנות מונחה עצמים - 2
קריסטן ניגורד ואולה יוהאן דאל - יוצרי סימולה
נראה שסימולה היא שפה עתיקה בסטנדרטים של תכנות, אבל הקשר ה"משפחתי" שלהם עם ג'אווה גלוי לעין בלתי מזוינת. סביר להניח שאתה יכול לקרוא בקלות את הקוד הכתוב עליו ולהסביר באופן כללי מה הוא עושה :)
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 מאפיינים עיקריים היוצרים יחד את פרדיגמת התכנות מונחה העצמים. הבנתם היא המפתח להפוך למתכנת מצליח. עקרונות של תכנות מונחה עצמים - 3

עקרון 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: הם משתמשים בקולות שלהם אחרת.

סיבות להופעת OOP

מדוע בכלל עלה רעיון התכנות החדש הזה - OOP ? למתכנתים היו כלים שעבדו: שפות פרוצדורליות, למשל. מה גרם להם להמציא משהו חדש ביסודו? קודם כל, סיבוך המשימות שעומדות בפניהם. אם לפני 60 שנה המשימה של מתכנת נראתה כמו "לחשב משוואה מתמטית כזו וכזו", עכשיו זה אולי נשמע כמו "ליישם 7 סופים שונים למשחק STALKER בהתאם להחלטות שהמשתמש קיבל ברגעי המשחק A, B, C, D , E, F ושילובים של פתרונות אלה." המשימות, כפי שאתה יכול לראות, הפכו בבירור למורכבות יותר בעשורים האחרונים. משמעות הדבר היא שסוגי הנתונים הפכו מורכבים יותר. זוהי סיבה נוספת להופעתה של OOP. את הדוגמה עם המשוואה ניתן לפתור בקלות באמצעות פרימיטיבים רגילים; אין צורך באובייקטים כאן. אבל יהיה קשה אפילו לתאר את הבעיה בסופים של המשחק מבלי להשתמש בכמה מחלקות שהמצאת. אבל יחד עם זאת, די קל לתאר את זה במחלקות ובאובייקטים: ברור שנצטרך את המחלקה Game, את המחלקה Stalker, את המחלקה Ending, את המחלקה של Player's Decision, את המחלקה של Game Moment, וכן הלאה. כלומר, גם בלי להתחיל לפתור בעיה, אנחנו יכולים בקלות לדמיין "סקיצות" של פתרונה בראשנו. המורכבות הגוברת של הבעיות אילצה את המתכנתים לחלק את הבעיה לחלקים. אבל בתכנות פרוצדורלי זה לא היה כל כך קל. ולעתים קרובות התוכנית הייתה "עץ" של חבורה של ענפים עם כל האפשרויות האפשריות להפעלתה. בהתאם לתנאים מסוימים, התוכנית בוצעה לאורך ענף כזה או אחר. עבור תוכניות קטנות אפשרות זו הייתה נוחה, אך חלוקת משימה גדולה לחלקים הייתה קשה מאוד. צורך זה הפך לסיבה נוספת להופעתה של OOP. הרעיון הזה נתן למתכנתים את היכולת לחלק תוכנית לחבורה של "מודולים" של מחלקות, שכל אחת מהן עשתה את החלק שלה בעבודה. כל האובייקטים, המקיימים אינטראקציה זה עם זה, יוצרים את עבודת התוכנית שלנו. בנוסף, ניתן לעשות שימוש חוזר בקוד שאנו כותבים במקום אחר בתוכנית, מה שגם חוסך זמן רב.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION