מחלקות מופשטות בפייתון

מחלקות מופשטות בפייתון

מאמר זה מסביר מחלקות מופשטות בפייתון.

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

YouTube Video

מחלקות מופשטות בפייתון

מודול abc של פייתון (מחלקות בסיס מופשטות) הוא חלק מהספרייה הסטנדרטית ומשמש להגדרת מחלקות מופשטות, המספקות תבנית לשיטות שמחלקה צריכה ליישם. השימוש במודול זה משפר את הגמישות והחוסן בתכנון מחלקות.

מהי מחלקה מופשטת?

מחלקות מופשטות הן מחלקות המשמשות להגדרת ממשק משותף למחלקות מוחשיות (ניתנות ליצירה). לא ניתן ליצור מופע ישיר של מחלקות מופשטות; יש לספק מימוש מוחשי במחלקות יורשות (תת-מחלקות).

מודול abc מאפשר לך להגדיר שיטות מופשטות או מאפיינים ולאכוף את מימושם במחלקות היורשות. אם אפילו שיטה מופשטת אחת אינה ממומשת, לא ניתן יהיה ליצור מופע של המחלקה.

כיצד להשתמש במודול abc

כדי ליצור מחלקה מופשטת באמצעות מודול abc, יש לרשת את מחלקת ABC ולהגדיר שיטות מופשטות באמצעות הדקורטור @abstractmethod.

 1from abc import ABC, abstractmethod
 2
 3# Definition of the abstract base class
 4class Animal(ABC):
 5
 6    @abstractmethod
 7    def sound(self):
 8        pass
 9
10# Concrete implementation in the subclass
11class Dog(Animal):
12    def sound(self):
13        return "Woof!"
14
15class Cat(Animal):
16    def sound(self):
17        return "Meow!"

כאן מוגדרת מחלקת Animal כמחלקה מופשטת המכילה שיטה מופשטת בשם sound. יש ליישם שיטה זו בצורה מוחשית בתת-המחלקות. Dog ו- Cat יורשות ממחלקת Animal וכל אחת מממשת את שיטת sound.

יצירת מופעים של מחלקות מופשטות

לא ניתן ליצור מופעים של מחלקות מופשטות ישירות. לדוגמה, ניסיון ליצור מופע של המחלקה Animal בעצמה יגרום לשגיאה.

1animal = Animal()  # TypeError: Can't instantiate abstract class Animal with abstract methods sound
  • כאשר מנסים ליצור מופע של מחלקה מופשטת, פייתון מזהה שיש שיטות מופשטות שלא מומשו ומחזיר שגיאת TypeError. אם כל השיטות המופשטות הנדרשות מומשו בתת-המחלקה, ניתן יהיה ליצור מופע.

שיטות מופשטות מרובות

ייתכן גם שלמחלקה יהיו שיטות מופשטות מרובות. אלא אם כן כל השיטות המופשטות מומשו בתת-המחלקה, המחלקה תישאר מחלקה מופשטת.

 1from abc import ABC, abstractmethod
 2
 3class Vehicle(ABC):
 4
 5    @abstractmethod
 6    def start_engine(self):
 7        pass
 8
 9    @abstractmethod
10    def stop_engine(self):
11        pass
12
13class Car(Vehicle):
14    def start_engine(self):
15        return "Car engine started"
16
17    def stop_engine(self):
18        return "Car engine stopped"

בדוגמה זו, המחלקה Vehicle כוללת שני מתודות מופשטות, והמחלקה Car יכולה להיות מופעלת רק לאחר מימוש שתי המתודות.

הגדרת מאפיינים מופשטים

המודול abc תומך לא רק במתודות מופשטות אלא גם במאפיינים מופשטים. דבר זה מאפשר להבטיח מימוש מאפיינים במחלקות היורשות.

 1from abc import ABC, abstractmethod
 2
 3class Shape(ABC):
 4
 5    @property
 6    @abstractmethod
 7    def area(self):
 8        pass
 9
10class Circle(Shape):
11    def __init__(self, radius):
12        self.radius = radius
13
14    @property
15    def area(self):
16        return 3.14159 * (self.radius ** 2)
  • בדוגמה זו, למחלקה Shape יש מאפיין מופשט area, ותת-המחלקה Circle מממשת את המאפיין הזה. כך, שימוש במחלקות מופשטות כדי להבטיח מימוש מאפיינים מסייע בשמירה על עקביות בקוד.

שימוש ב-isinstance() וב-issubclass()

שימוש במחלקות מופשטות מאפשר לאשר את קשרי הירושה בין מחלקות עם isinstance() או issubclass(), ובכך משפר את בטיחות וגמישות הקוד.

 1from abc import ABC, abstractmethod
 2
 3# Definition of the abstract base class
 4class Animal(ABC):
 5
 6    @abstractmethod
 7    def sound(self):
 8        pass
 9
10# Concrete implementation in the subclass
11class Dog(Animal):
12    def sound(self):
13        return "Woof!"
14
15class Cat(Animal):
16    def sound(self):
17        return "Meow!"
18
19class Vehicle(ABC):
20
21    @abstractmethod
22    def start_engine(self):
23        pass
24
25    @abstractmethod
26    def stop_engine(self):
27        pass
28
29class Car(Vehicle):
30    def start_engine(self):
31        return "Car engine started"
32
33    def stop_engine(self):
34        return "Car engine stopped"
35
36print("Dog() is an Animal? -> ", isinstance(Dog(), Animal))   # True
37print("Dog is subclass of Animal? -> ", issubclass(Dog, Animal))  # True
38print("Cat() is a Vehicle? -> ", isinstance(Cat(), Vehicle))  # False

הפונקציה isinstance() משמשת לבדיקה אם אובייקט הוא מופע של מחלקה מסוימת, ו-issubclass() משמשת לבדיקה אם מחלקה היא תת-מחלקה של מחלקה מסוימת.

סיכום

על ידי תכנון מחלקות מופשטות באמצעות המודול abc, ניתן להבהיר את הממשק בין מחלקות ולהבטיח מימוש המתודות והמאפיינים הנדרשים. דבר זה מסייע לשמירה על עקביות הקוד ולהפחתת שגיאות, ולכן הוא שימושי במיוחד בפרויקטים בקנה מידה גדול.

מחלקות מופשטות הן כלי חשוב ב-Python התומך בתכנות מונחה עצמים גמיש, ומשפר את יכולת השימוש החוזר והתחזוקה של מחלקות.

תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.

YouTube Video