5.5 הורשה הרצאה
הורשה - Inheritance¶
- הורשה זה קונספט בסיסי בOOP שמאפשר למחלקה לרשת מאפיינים ממחלקה אחרת.
דוגמה:
class Animal: def __init__(self, name): self.name = name class Dog(Animal): def speak(self): return f"{self.name} says Woof!" class Cat(Animal): def speak(self): return f"{self.name} says Meow!" # Example usage dog = Dog("Buddy") cat = Cat("Whiskers") print(dog.speak()) # Output: Buddy says Woof! print(cat.speak()) # Output: Whiskers says Meow! - במקרה הזה ניתן לראות שהמחלקות Dog ו - Cat יורשים מהמחלקה Animal.
- המתודה
__init__והשדהnameשל Animal עוברים בירושה לCat ו - Dog. - מה זה עוזר לנו? במקרה הזה אפשר לראות שקיצרנו את הקוד, במקום לממש פעמיים
__init__לשני המחלקות השתמשנו בהורשה. - טרמינלוגיה:
- מחלקת Animal - מחלקת אב (parent class), מחלקת על (super class), base class
- מחלקת Dog/Animal - מחלקת בת (child class), תת מחלקת (subclass), derived class
פולימורפיזם - Polymorphism¶
- מה אם נרצה בכל זאת לכתוב מתודת
__init__במחלקת ילד שלנו? איך נעשה את זה?
- נוכל לעשות את זה, רק קיימת בעיה, כאשר נעשה את זה אנחנו נדרוס את ה
__init__של המחלקת אב, אז אנחנו נרצה לפנות אלייה בתוך ה__init__של המחלקת ילד שלנו. נעשה זאת עם הפונקציה המובנתsuper, פונקציה זו מביאה לנו גישה למחלקת אב. - הדריסה הזו של הממברים שעשינו נקרא פולימורפיזם: פולי - הרבה, מורף - קריאות = (הרבה קריאות לאותה מתודה)
קונספט: המחלקה object¶
- בפייתון כל מחלקה יורשת מהמחלקה
object, המחלקה הזו היא המחלקה הבסיסית ביותר בפייתון, כולם יורשים ממנה. - נוכל להוכיח זאת עם שימוש בפונקציה המובנית
issubclass.
- המחלקה
objectהיא המחלקה הבסיסית ביותר בפייתון, היא מגדירה את כל המתודות קסם שקיימות בפייתון. כאשר אנחנו מיישמים מתודות קסם במחלקות שלנו - אנחנו בעצם דורסים את המתודות שמוגדרות במחלקהobject. - חשוב להכיר את הקונספט הזה כדי להכיר את פייתון לעומק יותר, זה פחות ישמש אותנו בכתיבת קוד.
מחלקות אבסטרקטיות¶
מתודות אבסטרקטיות¶
- לפעמים כשאנחנו כותבים מחלקת אב, אנחנו רוצים לחייב את כל המחלקות ילד שיורשים מהמחלקה ליישם איזשהי מתודה, זה נקרא "מתודה אבסטרקטית"
from abc import abstractmethod, ABC class Animal(ABC): def __init__(self, name): self.name = name @abstractmethod def speak(self): pass class Dog(Animal): def __init__(self, name, speed): self.speed = speed super().__init__(name) def speak(self): return f"{self.name} says Woof!" dog = Dog("Buddy", 5) - אנחנו יכולים להשתמש במודול המובנה בפייתון
abcכדי לעשותimportל -abstractmethodו -ABCשאנחנו יכולים להשתמש בהם כדי להגדיר מתודה אבסטרקטית, ניתן לראות למעלה איך עושים את זה. - שימו לב שאם
Dogלא היה ממש את המתודהspeakהייתה נזרקת שגיאה. - אז מפה מגיעה השאלה: למה שנרצה לחייב את מחלקת הבת לממש כל מיני מתודות?
- תשובה: כדי למנוע דברים לא צפויים -> אני רוצה לדאוג שכל מתכנת (כולל אני) כאשר הוא יוצר מחלקה שיורשת מהמחלקה שאני מגדיר יהיה חייב ליישם מתודות מסויימות, כדי למנוע הפתעות.
- איזה הפתעות? הנה דוגמה:
dog = Dog() cat = Cat() mouse = Mouse() animals = [dog, cat, mouse] for animal in animals: animal.speak()
בקוד הבא יצרנו 3 סוגים של חיות, הקוד הזה תלוי בכך שלכל החיות יש מתודה בשםspeak, אם אין לאחת החיות את המתודה הקוד יזרוק שגיאה. במקרה הזה נרצה להשתמש במתודה אבסטרקטית כדי לדאוג שלכל סוגי החיות יהיה את המתודהspeak
שדות אבסטרקטים¶
- כמו מתודות אבסטרקטיות, נוכל לעשות גם שדות אבסטרקטים שהמחלקת בת תהיה חייבת לממש
- ניתן לראות שאפשר לעשות אבסטרקציה לשדות ישירות עפ אנקפסולציה (property)
מחלקה אבסטרקטית¶
- חשוב לציין: המחלקה
Animalהיא מחלקה אבסטרקטית, כי היא מחילה ממברים אבסטרקטים. - איי אפשר לצור אובייקטים חדשים ממחלקה אבסטרקטית, כי חלק מהשדות/מתודות שלהם לא קיימות (לא מייושמות)
ממשק - אינטרפייס - Interface¶
- ממשק הוא מחלקה אבסטרקטית שכל הממברים שלה הם אבסטרקטים.
- מתי נשתמש בממשקים? כאשר נרצה לחייב מחלקות לענות על רשימת חוקים, הממשק הוא רשימת מתודות שהמחלקה חייבת ליישם.
הבדלים בין מחלקה אבסטרקטית לממשק¶
- מחלקה אבסטרקטית יכולה שיהיה לה מתודות רגילות ומתודות אבסטרקטיות.
- כל הממברים של ממשק חייבים להיות אבסטרקטים.