Kahibaro
Discord Login Register

وراثت (مقدماتی)

ایدهٔ وراثت: بازاستفاده و گسترش کلاس‌ها

در فصل شی‌ءگرا (OOP) با مفاهیم کلی کلاس و شیء، ویژگی‌ها و متدها آشنا شده‌اید. وراثت (Inheritance) ابزاری است که به شما اجازه می‌دهد:

به زبان ساده:

در این فصل فقط با وراثت ساده (تک‌وراثت) آشنا می‌شوید؛ مفاهیم پیچیده‌تر مثل وراثت چندگانه در این دوره پوشش داده نمی‌شود.


ساختن کلاس فرزند از روی کلاس پدر

سینتکس وراثت در پایتون:

class Parent:
    ...
class Child(Parent):
    ...

یعنی در پرانتز بعد از نام کلاس فرزند، نام کلاس پدر را می‌نویسیم.

یک مثال ساده:

class Animal:
    def speak(self):
        print("این حیوان صدایی درمی‌آورد.")
class Dog(Animal):
    pass  # فعلاً چیزی اضافه نمی‌کنیم
dog = Dog()
dog.speak()

در این‌جا:

خروجی:

این حیوان صدایی درمی‌آورد.

نکته: کلمهٔ pass یعنی «هیچ کاری نکن» و فقط برای خالی نماندن بدنهٔ کلاس استفاده شده است.


اضافه کردن ویژگی و متد جدید در کلاس فرزند

کلاس فرزند می‌تواند موارد جدید داشته باشد که در کلاس پدر وجود ندارند.

class Animal:
    def speak(self):
        print("این حیوان صدایی درمی‌آورد.")
class Dog(Animal):
    def bark(self):
        print("هاپ هاپ!")
dog = Dog()
dog.speak()  # از کلاس Animal
dog.bark()   # مخصوص کلاس Dog

در این مثال:

بازنویسی متدها (Override)

گاهی می‌خواهید کلاس فرزند همان متد کلاس پدر را داشته باشد،
اما رفتارش متفاوت باشد. در این صورت، متد را در کلاس فرزند بازنویسی می‌کنید.

class Animal:
    def speak(self):
        print("این حیوان صدایی درمی‌آورد.")
class Dog(Animal):
    def speak(self):  # بازنویسی متد پدر
        print("سگ می‌گوید: هاپ هاپ!")
class Cat(Animal):
    def speak(self):
        print("گربه می‌گوید: میاو میاو!")
animal = Animal()
dog = Dog()
cat = Cat()
animal.speak()
dog.speak()
cat.speak()

خروجی:

این حیوان صدایی درمی‌آورد.
سگ می‌گوید: هاپ هاپ!
گربه می‌گوید: میاو میاو!

نکتهٔ مهم:
نام متد و تعداد/نام پارامترهای آن در کلاس فرزند باید با کلاس پدر یکی باشد تا واقعاً «بازنویسی» محسوب شود.


وراثت و `__init__` (سازنده)

معمولاً کلاس‌ها یک متد __init__ دارند که هنگام ساخت شیء اجرا می‌شود.
در وراثت، دو حالت مهم داریم:

  1. کلاس فرزند از __init__ پدر همان‌طور که هست استفاده کند؛
  2. کلاس فرزند __init__ خودش را تعریف کند، ولی هم‌زمان کارهای __init__ پدر را هم انجام دهد.

استفادهٔ مستقیم از `__init__` پدر

اگر در کلاس فرزند __init__ تعریف نکنید، به طور خودکار از __init__ پدر استفاده می‌شود.

class Animal:
    def __init__(self, name):
        self.name = name
class Dog(Animal):
    pass
dog = Dog("آلفا")
print(dog.name)

اینجا:

استفاده از `super()` در کلاس فرزند

اگر بخواهید در کلاس فرزند:

از تابع super() استفاده می‌کنید.

class Animal:
    def __init__(self, name):
        self.name = name
class Dog(Animal):
    def __init__(self, name, breed):
        # صدا زدن سازندهٔ کلاس پدر
        super().__init__(name)
        # ویژگی اضافه مخصوص Dog
        self.breed = breed
dog = Dog("آلفا", "ژرمن شپرد")
print(dog.name)
print(dog.breed)

اینجا:

اگر super().__init__ را فراموش کنید، ویژگی‌هایی که در سازندهٔ کلاس پدر تعریف می‌شوند، در شیء فرزند وجود نخواهند داشت.


مثال کلی: کلاس پدر «وسیلهٔ نقلیه» و کلاس‌های فرزند

یک مثال کمی کامل‌تر:

class Vehicle:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model
    def info(self):
        print(f"وسیله نقلیه: {self.brand} {self.model}")
class Car(Vehicle):
    def __init__(self, brand, model, doors):
        super().__init__(brand, model)
        self.doors = doors
    def info(self):  # بازنویسی متد info
        print(f"ماشین: {self.brand} {self.model} با {self.doors} در")
class Motorcycle(Vehicle):
    def info(self):  # این‌جا فقط پیام را تغییر می‌دهیم
        print(f"موتور: {self.brand} {self.model}")
car = Car("Toyota", "Corolla", 4)
moto = Motorcycle("Yamaha", "R3")
car.info()
moto.info()

نکات مهم در این مثال:

چرا وراثت مفید است؟

چند مزیت مهم وراثت:

  1. کاهش تکرار کد
    چیزهای مشترک را یک‌بار در کلاس پدر می‌نویسید.
  2. مدل‌سازی بهتر دنیای واقعی
    مثلاً:
    • PersonStudent، Teacher
    • ShapeCircle، Rectangle
  3. گسترش آسان کد
    بدون دست‌زدن به کد کلاس پدر، می‌توانید کلاس‌های فرزند جدید بسازید.

نکات و اشتباهات رایج در وراثت

تمرین‌های پیشنهادی

برای تمرین (نیازی نیست در این فصل حل شوند، فقط پیشنهاد هستند):

  1. کلاسی به نام Person بسازید با ویژگی‌های name و age و یک متد introduce که خود را معرفی کند.
    سپس کلاس Student را بسازید که از Person ارث ببرد و ویژگی student_id داشته باشد و متد introduce را طوری بازنویسی کند که شمارهٔ دانشجویی را هم بگوید.
  2. کلاسی به نام Shape بسازید با متد area (فعلاً فقط print کند «مساحت تعریف نشده است»).
    سپس کلاس‌های Rectangle و Circle را از آن ارث ببرید و متد area را طوری بازنویسی کنید که مساحت را حساب و چاپ کنند.

در فصل‌های بعدی مثال‌های بیشتری از ترکیب وراثت با دیگر مفاهیم OOP خواهید دید.

Views: 5

Comments

Please login to add a comment.

Don't have an account? Register now!