CodeGym /בלוג Java /Random-HE /עקרונות OOP
John Squirrels
רָמָה
San Francisco

עקרונות OOP

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

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

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

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" על ידי Weekly-geekly. כפי שאתה יכול לראות, ג'אווה לא כל כך שונה מסבא שלה :) זה נובע מהעובדה שהופעתה של סימולה סימנה את הולדתו של מושג חדש: תכנות מונחה עצמים. ויקיפדיה מגדירה את OOP כך: "תכנות מונחה עצמים (OOP) היא פרדיגמת תכנות המבוססת על המושג "אובייקטים", שיכולה להכיל נתונים, בצורה של שדות (הידועים לעתים קרובות בתור תכונות), וקוד, בצורה של נהלים (המכונה לעתים קרובות שיטות)." לדעתי זו הגדרה ממש טובה. לא מזמן התחלת ללמוד ג'אווה, אבל ההגדרה הזו כנראה לא מכילה אף מילה שאתה לא יודע :) היום OOP היא מתודולוגיית התכנות הנפוצה ביותר. בנוסף ל-Java, עקרונות OOP משמשים בשפות פופולריות רבות שאולי שמעתם עליהן. לדוגמה, C++ (בשימוש פעיל בפיתוח משחקים), Objective-C ו-Swift (משמשים לכתיבת תוכניות עבור מכשירי אפל), Python (הפופולרי ביותר בלמידת מכונה), PHP (אחת משפות פיתוח האינטרנט הפופולריות ביותר), JavaScript ( קל יותר לומר למה זה לא משמש) ועוד רבים אחרים. אז מה הם בכלל העקרונות של OOP? נספר לך בפירוט.

עקרונות OOP

אלו הם היסודות של הקרן. 4 המאפיינים העיקריים היוצרים יחד את פרדיגמת התכנות מונחה העצמים. הבנתם חיונית כדי להפוך למתכנת מצליח.

עקרון 1. ירושה

חדשות טובות: אתה כבר מכיר כמה מהעקרונות של OOP! :) כבר נתקלנו בירושה כמה פעמים בשיעורים, והצלחנו להשתמש בה. ירושה הוא מנגנון המאפשר לך לתאר מחלקה חדשה על סמך מחלקה קיימת (הורה). בכך, המחלקה החדשה שואלת את המאפיינים והפונקציונליות של מחלקת האב. לשם מה מיועדת ירושה ואילו יתרונות היא מספקת? מעל הכל, שימוש חוזר בקוד. ניתן להשתמש בשדות ובשיטות המוצהרים במחלקות אב במחלקות צאצאות. אם לכל סוגי המכוניות יש 10 שדות נפוצים ו-5 שיטות זהות, אתה רק צריך להעביר אותם למחלקת האב Auto . אתה יכול להשתמש בהם בכיתות צאצאים ללא בעיות. יתרונות מוצקים: גם כמותי (פחות קוד) וכתוצאה מכך, איכותי (השיעורים הופכים לפשוטים הרבה יותר). יתרה מכך, הירושה היא מאוד גמישה - אתה יכול להוסיף פונקציונליות כתיבה נפרדת שחסרה לצאצאים (כמה שדות או התנהגות ספציפיים למחלקה מסוימת). באופן כללי, כמו בחיים האמיתיים, כולנו דומים במקצת להורים שלנו, אבל גם שונים מהם איכשהו :)

עקרון 2. הפשטה

זהו עיקרון מאוד פשוט. הפשטה פירושה לזהות את המאפיינים העיקריים והמשמעותיים ביותר של משהו, ובו זמנית להשליך כל דבר פעוט וחסר חשיבות. אין צורך להמציא את הגלגל מחדש. נזכיר דוגמה משיעור ישן על שיעורים. נניח שאנחנו יוצרים מערכת תיוק לעובדי החברה. כדי ליצור אובייקטים של "עובד", כתבנו כיתת Employee . אילו מאפיינים חשובים כדי לתאר אותם במערכת התיוק של החברה? שם, תאריך לידה, SSN ומזהה עובד. אבל לא סביר שנזדקק לגובה, צבע עיניים או צבע שיער של העובד לתיעוד מסוג זה. לחברה אין צורך במידע כזה על עובד. לכן, במחלקת Employee , אנו מצהירים על המשתנים הבאים: String name , int age , int socialSecurityNumber ו- int employeeId . ואנחנו מפשטים מידע מיותר כמו צבע עיניים. עם זאת, אם אנחנו יוצרים מערכת תיוק עבור סוכנות דוגמנות, המצב משתנה באופן דרמטי. גובה, צבע עיניים וצבע שיער של דוגמנית הם מאפיינים חשובים, אבל ה-SSN שלה ממש לא רלוונטי עבורנו. אז, במחלקה Model , אנו יוצרים את המשתנים הבאים: String height , String hair , String eyes .

עקרון 3. אנקפסולציה

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

Cat.age = -1000;
מנגנון האנקפסולציה מאפשר לנו להגן על שדה הגיל בשיטת קבע, שבה נוכל להבטיח שלא ניתן להגדיר את הגיל למספר שלילי.

עקרון 4. פולימורפיזם

פולימורפיזם הוא היכולת לעבוד עם מספר סוגים כאילו היו אותו סוג. יתרה מכך, התנהגות האובייקטים תהיה שונה בהתאם לסוגם. זה נשמע מסובך? בואו נבין את זה עכשיו. קח את הדוגמה הפשוטה ביותר: בעלי חיים. צור מחלקה של Animal עם שיטה אחת של speak() ושתי מחלקות משנה - Cat and Dog .

public class Animal {

   public void speak() {
      
       System.out.println("Hello!");
   }
}

public class Dog extends Animal {
  
   @Override
   public void speak() {
       System.out.println ("Woof-woof!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}
כעת ננסה להכריז על משתנה התייחסות לבעלי חיים ולהקצות לו אובייקט Dog .

public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.speak();
   }
}
איזו שיטה לדעתך תיקרא? Animal.speak() או Dog.speak() ? השיטה בכיתת Dog תיקרא: ווף-ווף! יצרנו הפניה לבעלי חיים , אבל האובייקט מתנהג כמו כלב . במידת הצורך, הוא יכול להתנהג כמו חתול, סוס או חיה אחרת. הדבר החשוב הוא להקצות תת-מחלקה ספציפית למשתנה ההתייחסות הכללי של Animal . זה הגיוני, כי כל הכלבים הם חיות. זה מה שחשבנו כשאמרנו "התנהגות החפצים תהיה שונה בהתאם לסוג שלהם". אם יצרנו אובייקט של חתול ...

public static void main(String[] args) {

   Animal cat = new Cat();
   cat.speak();
}
שיטת speak() תציג את "מיאו!" אבל למה אנחנו מתכוונים ב'יכולת לעבוד עם כמה סוגים כאילו הם אותו סוג'? זה גם די פשוט. בואו נדמיין שאנחנו יוצרים מספרה לבעלי חיים. המספרה שלנו אמורה להיות מסוגלת לתת לכל בעל חיים לקצץ, אז אנחנו יוצרים שיטת trim() עם פרמטר Animal (החיה המסתפרת).

public class AnimalBarbershop {

   public void trim(Animal animal) {

       System.out.println("The haircut is done!"); 
   }
}
ועכשיו אנחנו יכולים להעביר חפצי חתול וכלב לשיטת trim() !

public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.trim(cat);
   barbershop.trim(dog);
}
והנה הדוגמה הברורה: כיתת AnimalBarbershop עובדת עם סוגי החתול והכלב כאילו הם אותו סוג. יחד עם זאת, לחתול ולכלב יש התנהגויות שונות: כל אחד מהם מדבר אחרת .

למה אנחנו צריכים OOP?

מדוע OOP בכלל עלה כקונספט תכנות חדש? למתכנתים היו כלים מתפקדים, כמו שפות פרוצדורליות. מה גרם להם להמציא משהו חדש ביסודו? מעל הכל, מורכבות המשימות שעומדות בפניהם. אם לפני 60 שנה המשימה של המתכנת הייתה משהו כמו "להעריך ביטוי מתמטי כלשהו", עכשיו זה יכול להיות משהו כמו "ליישם 7 סופים שונים למשחק STALKER, בהתאם לשילובים של החלטות השחקן שהתקבלו בנקודות A, B, C, DE , ו-F במשחק." כפי שאתה יכול לראות, ברור שהמשימות הפכו מסובכות יותר בעשורים האחרונים. וכתוצאה מכך, סוגי הנתונים הפכו מסובכים יותר. זו סיבה נוספת לכך ש-OOP הופיע. ניתן להעריך ביטוי מתמטי בקלות באמצעות פרימיטיבים רגילים. אין צורך בחפצים כאן. אבל את המשימה עם סיום המשחק יהיה קשה אפילו לתאר מבלי להשתמש במחלקות מותאמות אישית. עם זאת, די קל לתאר את זה באמצעות מחלקות ואובייקטים. ברור שנזדקק למספר מחלקות: משחק, סטאלקר, סיום, החלטה של ​​שחקן, GameEvent וכן הלאה. במילים אחרות, גם בלי להתחיל לפתור את הבעיה, אנחנו יכולים בקלות "לשרטט" פתרון בראש. המורכבות הגוברת של המשימות אילצה את המתכנתים לחלק אותן לחלקים. אבל זה לא היה כל כך קל לעשות בתכנות פרוצדורלי. ולעתים קרובות תוכנית הייתה כמו עץ ​​עם הרבה ענפים המייצגים את כל נתיבי הביצוע האפשריים. בהתאם לתנאים מסוימים, בוצע סניף כזה או אחר של התוכנית. עבור תוכניות קטנות זה היה נוח, אבל היה קשה מאוד לחלק בעיה גדולה לחלקים. זו הייתה סיבה נוספת להופעתה של OOP. הפרדיגמה הזו נתנה למתכנתים את היכולת לחלק תוכנית לחבורה של "מודולים" (מחלקות), שכל אחד מהם עושה את החלק שלו בעבודה. על ידי אינטראקציה זה עם זה, כל האובייקטים משיגים את עבודת התוכנית שלנו. בנוסף, אנחנו יכולים לעשות שימוש חוזר בקוד שלנו במקום אחר בתוכנית, מה שגם חוסך הרבה זמן.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION