Menu
Coddy logo textTech

מחלקות ומתודות אבסטרקטיות

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 כדי ליצור מחלקות מופשטות. על מחלקות יורשות לממש את כל המתודות המופשטות, אחרת גם הן יהיו מופשטות. כך מובטחת עקביות ונמנעים מימושים חלקיים.

challenge icon

אתגר

בינוני

באתגר הזה תממשו מערכת לעיבוד תשלומים.

עליכם להשלים את המימוש בקבצים האלה:

  • 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()  # אי אפשר ליצור מופע של מחלקה מופשטת
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Python אונליין