מחלקות ומתודות אבסטרקטיות
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Python של Coddy. שיעור 25 מתוך 64.
מחלקות מופשטות הן מחלקות שאי אפשר ליצור מהן מופעים ישירות, והן מכילות מתודות מופשטות שמחלקות משנה חייבות לממש.
חשבו על זה כמו על טופס: מחלקה מופשטת היא כמו טופס חובה שחלק מהשדות בו נדרשים (מתודות מופשטות) וחלקם אופציונליים (מתודות קונקרטיות). אי אפשר לשלוח את הטופס עצמו — קודם צריך למלא את כל השדות הנדרשים. באופן דומה, אי אפשר ליצור מופעים של מחלקה מופשטת עד שכל המתודות המופשטות ממומשות במחלקת משנה.
ייבא את המודול abc כדי ליצור מחלקות מופשטות:
from abc import ABC, abstractmethodצרו מחלקה מופשטת עם מתודות מופשטות:
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # מתודה קונקרטית (יש לה מימוש)המעטר @abstractmethod מסמן מתודות שחייבות להיות ממומשות במחלקות יורשות — אלה ה״שדות הנדרשים״ בטופס שלך. למתודות רגילות כמו describe() יכולות להיות מימושים, והן עוברות בירושה כפי שהן — אלה ה״שדות שמולאו מראש״.
למה להשתמש במחלקות מופשטות? הן אוכפות חוזה. אם תיצרו מחלקת Shape, אתם אומרים: "כל צורה חייבת להיות מסוגלת לחשב את השטח ואת ההיקף שלה." כך נמנעים באגים שעלולים להתרחש אם שוכחים לממש מתודות חיוניות.
נסו ליצור מופע של המחלקה המופשטת:
# זה יגרום לשגיאה:
# shape = Shape() # TypeError: אי אפשר ליצור מופע של מחלקה מופשטתהשגיאה הזאת מכוונת — זה כמו לנסות לשלוח טופס ריק. Python אומר: "עדיין לא מילאתם את השדות הנדרשים (המתודות area ו-perimeter)!"
צרו תת־מחלקה קונקרטית שמממשת את כל המתודות המופשטות:
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radiusעכשיו "מילאנו את כל השדות הנדרשים" — מימשנו גם את area() וגם את perimeter(). המחלקה Circle היא כעת מחלקה קונקרטית ומלאה שאפשר ליצור ממנה מופעים.
עכשיו אפשר ליצור מופעים של המחלקה הקונקרטית:
circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe()) # מתודה קונקרטית שעברה בירושהצרו מחלקת משנה קונקרטית נוספת:
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width self.height
def perimeter(self):
return 2 * (self.width + self.height)
rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())פלט:
78.5
31.400000000000002
This is a shape
24
20מחלקות מופשטות מגדירות חוזה שעל מחלקות יורשות לפעול לפיו. השתמשו ב־ABC וב־@abstractmethod כדי ליצור מחלקות מופשטות. על מחלקות יורשות לממש את כל המתודות המופשטות, אחרת גם הן יהיו מופשטות. כך מובטחת עקביות ונמנעים מימושים חלקיים.
אתגר
בינוניבאתגר הזה תממשו מערכת לעיבוד תשלומים.
עליכם להשלים את המימוש בקבצים האלה:
paymentmethod.py- מחלקת בסיס מופשטת עם לוגיקת אימותcreditcard.py- מימוש של תשלום בכרטיס אשראיpaypal.py- מימוש של תשלום ב-PayPal
פעלו לפי הערות ה-TODO בכל קובץ כדי לממש את הפונקציונליות הנדרשת. ההערות ינחו אתכם צעד אחר צעד ביצירת מתודות מופשטות, במימוש תתי-מחלקות קונקרטיות ובהגדרת קשרי הייבוא המתאימים בין הקבצים.
הקובץ driver.py מכיל מקרי בדיקה שיוודאו שהמימוש שלכם פועל כראוי, באמצעות עיבוד תרחישי תשלום שונים והצגת פרטים מתאימים לכל אמצעי תשלום.
נסו בעצמכם
from creditcard import CreditCard
from paypal import PayPal
# בדקו את המימושים - אין לשנות את קוד הבדיקה הזה
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")
# עבדו תשלומים תקינים
if cc.validate(100):
print(cc.process_payment(100))
print(cc.payment_details())
if pp.validate(200):
print(pp.process_payment(200))
print(pp.payment_details())
# נסו סכום לא תקין
if not pp.validate(0):
print("Invalid payment amount")
# ביטול סימון ההערה כאן יגרום לשגיאה:
# pm = PaymentMethod() # אי אפשר ליצור מופע של מחלקה מופשטתהשיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםהפרמטר selfמתודותמאפייניםשיטת הבנאי (__init__)חזרה: מחשבון פשוט5פולימורפיזם
בחינה מחדש של דריסת מתודותטיפוסיות ברווזמחלקות ומתודות אבסטרקטיותעיצוב ממשקיםסיכום – מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה לעומת הורשהMixinsמתודות סטטיות ומתודות מחלקהדקורטורים למחלקותמנהלי הקשרתרגלו בעצמכם: קומפיילר Python אונליין