همه چیز درباره پلی مورفیسم (چند ریختی) در برنامه نویسی

پلی مورفیسم یا چند ریختی در برنامه نویسی
تاریخ بروزرسانی : 11 آبان 1402 | تعداد بازدید : 1748 | زمان خواندن مقاله : 20 دقیقه
پیرامون برنامه نویسی،

صفر تا صد پلی مورفیسم در برنامه نویسی

پلی مورفیسم در برنامه نویسی از آن مباحث مهمی است که هر برنامه نویسی، چه مبتدی و چه حرفه ای، باید آن را بیاموزد. در واقع پلی مورفیسم یکی از مباحث شی گرایی محسوب می‌شود که ما در این مطلب از درسمن می‌خواهیم علاوه‌بر معرفی و بیان انواع آن، این مبحث را با یک مثال در زبان‌های پایتون، سی‌شارپ، جاوا و سی‌پلاس‌پلاس، بهتر درک کنید. پس به شما دوست عزیز پیشنهاد می‌کنیم که اگر علاقه‌مند به یادگیری مباحث دنیای برنامه‌نویسی هستی، تا پایان موضوع امروز همراه ما باشید.

پلی مورفیسم در برنامه نویسی چیست؟

معرفی پلی مورفیسم در برنامه نویسی

چند شکلی یا چند ریختی، یکی از مفاهیم اصلی برنامه نویسی شی گرا (OOP) است و موقعیت‌هایی را توصیف می‌کند که یک شی در اشکال مختلفی فراخوانی می‌شود. در واقع پلی مورفیسم این موضوع را بیان می‌کند که از طریق یک رابط، به انواع اشیا مختلف دسترسی پیدا کنید. 

 اگر بخواهیم یک مثال واقعی از پلی مورفیسم بزنیم باید به نقش انسان‌ها در زندگی اشاره کنیم که یک فرد به طور همان زمان، می‌تواند نقش‌های متفاوتی داشته باشد؛ مثلا یک خانم در عین داشتن نقش مادر در خانواده، می‌تواند نقش‌های دیگر مانند همسر، کارمند و حتی دختر هم داشته باشد. پس می‌بینیم که جنسیت یک خانم می‌تواند نقش های زیادی داشته باشد که هر یک از آن‌ها براساس موقعیت و شرایط خود اجرا می‌شود.

به بیان ساده‌تر می‌توان گفت Polymorphism خاصیتی است که از طریق آن می‌توان هر پیامی را به اشیا چندین کلاس ارسال کرد تا هر شی را بسته به ویژگی‌های کلاس، به روش مناسب پاسخ دهد. در حقیقت پلی مورفیسم یک روشی در شی گرایی و بسته به کلاسی است که شی، آن را فراخوانی می‌کند تا کارهای مختلفی انجام گیرد.

معرفی انواع پلی مورفیسم در برنامه نویسی

بطورکلی انواع پلی مورفیسم به دو دسته تقسیم می‌شوند که شامل موارد زیر هستند:

  • پلی‌مورفیسم کامپایلی (Compile-time Polymorphism)

در این نوع پلی‌مورفیسم، شما می‌توانید توابعی با نام یکسان در یک کلاس را تعریف کنید، اما با تعداد یا نوع پارامترهای مختلف. در واقع کامپایلر بر اساس تعداد و نوع پارامترها تصمیم می‌گیرد که کدام تابع را فراخوانی کند. برای مثال تابع ماشین حسابی که می‌تواند با دو عدد صحیح یا دو عدد اعشاری عملیات جمع را انجام دهد، از نوع پلی‌مورفیسم کامپایلری به حساب می‌آید.

  • پلی‌مورفیسم زمان اجرا (Runtime Polymorphism)

در این نوع پلی‌مورفیسم، کلاس‌های مشتق شده (زیرکلاس‌ها) می‌توانند تابع‌هایی که از کلاس پایه (سوپرکلاس) به ارث برده‌اند را با پیاده‌سازی‌های خود بازنویسی کنند. پس این نوع در زمان اجرا برنامه متوجه تابع مناسب خود می‌شود. برای مثال در کلاس انسان با تابع خوردن، می‌تواند در کلاس‌های مشتق شده مانند زن و مرد، به شکل خاصی بازنویسی شود.

روش‌های پیاده‌سازی پلی مورفیسم

حال که با پلی مورفیسم و انواع آن آشنا شده‌اید، می‌خواهیم روش‌های پیاده سازی آن را بیان کنیم که شامل موارد زیر است:

  • ارث‌بری (Inheritance) 

در این روش، یک کلاس مشتق (فرزند) از یک کلاس پایه (والد) ایجاد می‌شود و متدهای پایه در کلاس مشتق بازنویسی می‌شوند. این روش که بر اساس نوع شی، متد مناسب به صورت پلی‌مورفیک را فراخوانی میکند، به برنامه‌نویس این امکان را می‌دهد تا عملیات‌های مشابه برای اشیا مختلف، پیاده‌سازی شود.

  • واسطه (Interface)

در زبان‌های برنامه‌نویسی مانند Java و C#، شما می‌توانید از واسطه‌ها (interface) برای تعریف پلی مورفیسم استفاده کنید. در واقع واسطه‌ها یک تعریف از متدها بدون پیاده‌سازی‌ واقعی آن‌ها است که کلاس‌ها می‌توانند از آن‌ها به عنوان یک قرارداد استفاده کنند. 

  • توابع ویژه (Function Overloading)

این روش پلی‌مورفیسم برای زبان‌هایی مانند C++ که از توابع ویژه (overloading) استفاده می‌کنند، به کار رفته می‌شود و شما می‌توانید چندین نسخه از یک تابع با نام یکسان ایجاد کنید اما با لیست پارامترهای مختلف؛ سپس تابع را مناسب با تعداد و نوع پارامترها، فراخوانی می‌کنید.

  • توابع کالبک (Callback Functions) 

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

  • متد‌های اجرایی (Runtime Polymorphism)

این روش پلی‌مورفیسم به وسیله تعیین نوع شی در زمان اجرا، ارائه می‌شود که در زبان‌هایی مانند Java و سی‌شارپ با استفاده از واژه‌کلیدی virtual و override استفاده می‌شود. در حقیقت متدهایی که به صورت مجازی (virtual) تعریف شده‌اند، در زمان اجرا براساس نوع واقعی شی صدا زده می‌شوند.

به طورکلی در همه روش‌ها، هدف اصلی پلی‌مورفیسم این است که به برنامه‌نویس امکان ایجاد کدی با قابلیت انعطاف‌پذیری را بدهد تا اشیا مختلف با رفتارها، توابع یا متدهای متفاوت را پیاده‌سازی کند.

مزایا و معایب پلی مورفیسم در برنامه نویسی چیست؟

معرفی مزایا و معایب پلی مورفیسم در برنامه نویسی

از مزایای پلی مورفیسم باید موارد زیر را معرفی کرد:

  • انعطاف‌پذیری (Flexibility)

پلی‌مورفیسم به شما این امکان را می‌دهد تا به راحتی عملیات‌های مشابه برای اشیا مختلف پیاده‌سازی کنید. این انعطاف‌پذیری باعث استفاده مجدد از کدها و انجام تغییرات بدون ایجاد تغییر در کد اصلی می‌شود.

  • خواناتر بودن کدها (Readability)

با استفاده از پلی‌مورفیسم، کدها خواناتر و مدیریت آن‌ها راحت‌تر می‌شود. به عنوان مثال، اگر تابعی یک نوع شی را به عنوان ورودی بپذیرد و عملیات مرتبط با آن نوع شی را انجام دهد، کد شما به نسبت به استفاده از مجموعه‌های شرطی (if/else) خواناتر می‌شود.

اما برخی از معایب پلی مورفیسم نیز به شرح زیر است:

  • پیچیدگی (Complexity)

 استفاده از پلی‌مورفیسم ممکن است پیچیدگی کد را افزایش دهد، زیرا باید کلاس‌ها، توابع و روش‌ها را با دقت، طراحی و مدیریت کرد که این می‌تواند برای تیم‌های برنامه‌نویسی، پیچیدگی ایجاد کند.

  • پیش‌فرض‌سازی (Defaulting)

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

  • کاهش کارایی (Performance)

استفاده بی‌رویه از پلی‌مورفیسم بدون دقت ممکن است به کاهش کارایی برنامه منجر شود، چراکه در اجرای این روش برخی از زبان‌ها، هزینه‌های بیشتری را رقم می‌زند.
به طور کلی، پلی‌مورفیسم یک اصل قدرتمند و مفید در برنامه‌نویسی است که در موارد مناسب می‌تواند کارایی کد را بهبود و انعطاف‌پذیری برنامه را افزایش دهد که البته برنامه‌نویسان باید نسبت مزایا و معایب استفاده آن، آگاهی داشته باشند.

بررسی پلی مورفیسم در زبان‌های مختلف

فرض ما دو کلاس به نام‌های Dog و Cat داریم که از کلاس Animal ارث‌بری کرده‌اند و هر کلاس، تابع make_sound را بازنویسی می‌کنند. سپس ما با ایجاد یک تابع به نام animal_sounds، یک شی از نوع Animal را به عنوان ورودی پذیرفته و تابع make_sound را اجرا می‌کنیم. در نهایت، با ایجاد شی‌های Dog و Cat و فراخوانی تابع animal_sounds روی آن‌ها، می‌توانیم پلی‌مورفیسم زمان اجرا را مشاهده کنیم، زیرا تابع مناسب با توجه به نوع شی فراخوانی می‌شود؛ به این ترتیب نمونه کد این مثال در زبان‌های مختلف به شرح زیر است:

  • پایتون

class Animal:
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        return "Woof!"

class Cat(Animal):
    def make_sound(self):
        return "Meow!"

# تابعی که شیء‌های مختلف را به عنوان ورودی می‌پذیرد
def animal_sounds(animal):
    return animal.make_sound()

# ایجاد شیء‌ها
dog = Dog()
cat = Cat()

# فراخوانی تابع با شیء‌های مختلف
print(animal_sounds(dog))  # خروجی: "Woof!"
print(animal_sounds(cat))  # خروجی: "Meow!"
  • سی‌شارپ


using System;

class Animal {
    public virtual void MakeSound() {
        Console.WriteLine("Animal makes a sound");
    }
}

class Dog : Animal {
    public override void MakeSound() {
        Console.WriteLine("Dog barks");
    }
}

class Cat : Animal {
    public override void MakeSound() {
        Console.WriteLine("Cat meows");
    }
}

class Program {
    static void Main(string[] args) {
        Animal myPet;

        myPet = new Dog();
        myPet.MakeSound(); // اجرای تابع MakeSound در کلاس Dog

        myPet = new Cat();
        myPet.MakeSound(); // اجرای تابع MakeSound در کلاس Cat
    }
}
  • جاوا


class Animal {
    public void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Cat meows");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        Animal myPet;

        myPet = new Dog();
        myPet.makeSound(); // اجرای تابع makeSound در کلاس Dog

        myPet = new Cat();
        myPet.makeSound(); // اجرای تابع makeSound در کلاس Cat
    }
}
  • سی‌پلاس پلاس


 #include <iostream>

class Animal {
public:
    virtual void makeSound() {
        std::cout << "Animal makes a sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        std::cout << "Dog barks" << std::endl;
    }
};

class Cat : public Animal {
public:
    void makeSound() override {
        std::cout << "Cat meows" << std::endl;
    }
};

int main() {
    Animal* myPet;

    Dog dog;
    Cat cat;

    myPet = &dog;
    myPet->makeSound(); // اجرای تابع makeSound در کلاس Dog

    myPet = &cat;
    myPet->makeSound(); // اجرای تابع makeSound در کلاس Cat

    return 0;
}
  • پی‌اچ‌پی


<?php
class Animal {
    public function makeSound() {
        return "Animal makes a sound";
    }
}

class Dog extends Animal {
    public function makeSound() {
        return "Dog barks";
    }
}

class Cat extends Animal {
    public function makeSound() {
        return "Cat meows";
    }
}

$dog = new Dog();
$cat = new Cat();

echo "Dog says: " . $dog->makeSound() . "<br>";
echo "Cat says: " . $cat->makeSound() . "<br>";
?>

در نهایت

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

در نتیجه، اگر شماهم به دنبال آموزش بهتر این مفهوم در زبان‌های مختلفی چون سی شارپ، پایتون، جاوا، سی پلاس پلاس و PHP هستید، حتما به دوره‌های آموزشی هر یک از زبان‌های ارائه شده توسط درسمن مراجعه کرده تا یادگیری این مبحث پیچیده با توانمندی و بیان ساده مدرس دوره برای شما شیرین و جذاب شود. پس اگر بازهم سوالی درباره پلی مورفیسم ذهن شما را به خود مشغول کرده است، حتما آن را در بخش نظرات با ما به اشتراک بگذارید.