تا اینجا با مفاهیم مهم برنامهنویسی شیءگرا مانند Class، Object، Method، Inheritance و Encapsulation آشنا شدیم.
حالا به یکی دیگر از مفاهیم مهم OOP یعنی Polymorphism یا چندریختی میرسیم.
چندریختی چیست؟
واژه Polymorphism از دو بخش تشکیل شده است: Poly به معنی «چند» و Morph به معنی «شکل».
در برنامهنویسی، چندریختی یعنی یک رابط یا متد بتواند در Objectهای مختلف رفتار متفاوتی داشته باشد.
یک نام یا روش استفاده میتواند برای چند Object یکسان باشد، اما هر Object رفتار مخصوص خودش را داشته باشد.
یک مثال ساده
فرض کنید چند حیوان داریم و همه آنها متدی به نام
speak()
دارند.
class Dog:
def speak(self):
print("Woof")
class Cat:
def speak(self):
print("Meow")
dog = Dog()
cat = Cat()
dog.speak()
cat.speak()
خروجی:
Woof Meow
همان نام
speak()
در دو کلاس استفاده شده است،
اما هر Object رفتار متفاوتی دارد.
چندریختی با یک تابع
یکی از نکات جالب این است که میتوانیم تابعی بنویسیم که با Objectهای مختلف کار کند.
class Dog:
def speak(self):
print("Woof")
class Cat:
def speak(self):
print("Meow")
def animal_sound(animal):
animal.speak()
dog = Dog()
cat = Cat()
animal_sound(dog)
animal_sound(cat)
خروجی:
Woof Meow
تابع
animal_sound()
لازم نیست بداند Object دقیقاً از چه کلاسی ساخته شده است.
فقط کافی است Object متد
speak()
را داشته باشد.
چندریختی با وراثت
یکی از کاربردهای مهم چندریختی در کنار Inheritance یا وراثت است.
فرض کنید یک کلاس والد به نام
Animal
داریم.
class Animal:
def speak(self):
print("Animal sound")
class Dog(Animal):
def speak(self):
print("Woof")
class Cat(Animal):
def speak(self):
print("Meow")
در اینجا کلاسهای
Dog
و
Cat
از
Animal
ارثبری کردهاند.
بازنویسی متد یا Method Overriding
وقتی کلاس فرزند یک متد موجود در کلاس والد را با رفتار جدید تعریف میکند، به این کار Method Overriding یا بازنویسی متد میگوییم.
class Animal:
def speak(self):
print("Some sound")
class Dog(Animal):
def speak(self):
print("Woof")
class Cat(Animal):
def speak(self):
print("Meow")
animals = [Dog(), Cat()]
for animal in animals:
animal.speak()
خروجی:
Woof Meow
حلقه فقط یک بار از
speak()
استفاده میکند،
اما هر Object رفتار مخصوص خودش را اجرا میکند.
یک مثال واقعیتر
فرض کنید در یک برنامه پرداخت، روشهای مختلف پرداخت داریم: کارت بانکی و کیف پول دیجیتال.
class CardPayment:
def pay(self, amount):
print(f"پرداخت {amount} تومان با کارت")
class WalletPayment:
def pay(self, amount):
print(f"پرداخت {amount} تومان با کیف پول")
def make_payment(payment_method, amount):
payment_method.pay(amount)
card = CardPayment()
wallet = WalletPayment()
make_payment(card, 100000)
make_payment(wallet, 200000)
خروجی:
پرداخت 100000 تومان با کارت پرداخت 200000 تومان با کیف پول
تابع
make_payment()
فقط میداند Object موردنظر متدی به نام
pay()
دارد.
بنابراین لازم نیست برای هر روش پرداخت یک تابع جداگانه بنویسیم.
چندریختی و حلقهها
چندریختی زمانی بسیار مفید میشود که بخواهیم با مجموعهای از Objectهای مختلف کار کنیم.
class Dog:
def speak(self):
return "Woof"
class Cat:
def speak(self):
return "Meow"
class Cow:
def speak(self):
return "Moo"
animals = [Dog(), Cat(), Cow()]
for animal in animals:
print(animal.speak())
خروجی:
Woof Meow Moo
Duck Typing در پایتون
پایتون در بسیاری از موارد از روشی به نام Duck Typing استفاده میکند.
ایده اصلی آن این است که به جای اینکه فقط به نوع Object توجه کنیم، بررسی کنیم آیا Object رفتار یا متد موردنیاز را دارد یا نه.
اگر Object متد
speak()
را داشته باشد،
میتوانیم در کدی که به این متد نیاز دارد از آن استفاده کنیم؛
مهم نیست Object دقیقاً از چه کلاس مشخصی ساخته شده باشد.
مزایای چندریختی
- کاهش تکرار کد
- انعطافپذیری بیشتر برنامه
- امکان استفاده از یک رابط برای Objectهای مختلف
- سادهتر شدن توسعه پروژه
- سازگاری بهتر بین بخشهای مختلف برنامه
تفاوت وراثت و چندریختی
- Inheritance: برای ایجاد رابطه بین کلاسها و به ارث بردن ویژگیها و متدها استفاده میشود.
- Polymorphism: اجازه میدهد Objectهای مختلف از یک رابط یا متد مشابه، رفتارهای متفاوتی داشته باشند.
تمرین عملی
سه کلاس به نامهای Car، Motorcycle و Truck ایجاد کنید.
هر کلاس باید متدی به نام
move()
داشته باشد.
برای هر کلاس پیام متفاوتی چاپ کنید.
سپس Objectهای هر سه کلاس را داخل یک لیست قرار دهید
و با یک حلقه، متد
move()
را اجرا کنید.
جمعبندی
چندریختی یکی از مفاهیم مهم برنامهنویسی شیءگرا است. با استفاده از آن میتوانیم یک رابط یا متد مشابه را برای Objectهای مختلف استفاده کنیم، در حالی که هر Object رفتار مخصوص خودش را دارد.
در این درس یاد گرفتیم:
- Polymorphism چیست.
- چندریختی با متدهای مشابه چگونه کار میکند.
- چگونه با وراثت چندریختی ایجاد کنیم.
- Method Overriding چیست.
- Duck Typing در پایتون چیست.
- چگونه چندریختی را در پروژههای واقعی استفاده کنیم.