دوره‌ها / JAVA / چندریختی (Java Polymorphism)

چندریختی (Java Polymorphism)

15 دقیقه Article

چندریختی (Polymorphism): یک دستور، چندین رفتار 🎭✨

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

۱. بازنویسی متد (Method Overriding)

وقتی کلاس فرزند متدی با همان نامِ والد می‌سازد تا رفتارِ مخصوص خودش را داشته باشد، می‌گوییم Overriding رخ داده است:

{code_block('class Animal {\n public void sound() { System.out.println("Animal sound"); }\n}\n\nclass Pig extends Animal {\n public void sound() { System.out.println("Oink Oink"); }\n}')}

۲. قدرت چندریختی ⚡

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

{code_block('Animal myPig = new Pig();\nAnimal myDog = new Dog();\nmyPig.sound(); // چاپ می‌کند: Oink\nmyDog.sound(); // چاپ می‌کند: Woof')}
تفاوت با Overloading: در Overloading نام یکیست ولی پارامترها فرق دارند. در Overriding همه چیز (نام، پارامتر، خروجی) دقیقاً یکیست، فقط پیاده‌سازی فرق می‌کند.

چرا چندریختی؟

چون به ما اجازه می‌دهد کدی بنویسیم که با "مفاهیم کلی" کار کند. مثلاً تابعی که لیستِ حیوانات را می‌گیرد و می‌گوید همگی صدا بدهند، بدون اینکه بداند هر کدام دقیقاً چه حیوانی هستند.

@Override: همیشه بالای متدهای بازنویسی شده از این انوتیشن استفاده کنید. این کار به کامپایلر کمک می‌کند تا مطمئن شود شما واقعاً در حال بازنویسی هستید و اشتباه تایپی ندارید.
<hr style="margin: 50px 0; border: 0; border-top: 1px dashed rgba(255,255,255,0.1);">

بخش تخصصی: معماری سیستم‌های شیءگرا 🏗️💎

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

۱. کد تمیز و اصل ابزارمندی (Abstraction)

در پروژه‌های بزرگ صنعتی، ما سعی می‌کنیم تا حد امکان وابستگی‌ها (Dependencies) را کاهش دهیم. استفاده درست از Interface و Abstract Class باعث می‌شود کدهای ما انعطاف‌پذیر باشند. به قولی: "برنامه‌نویسی برای اینترفیس، نه برای پیاده‌سازی".

۲. مدیریت پکیج‌ها و جلوگیری از تداخل

پکیج‌بندی حرفه‌ای فقط برای نظم نیست؛ بلکه برای کنترلِ Visibility است. با استفاده درست از سطوح دسترسی (مثل protected و default) در سطح پکیج، می‌توانید از دسترسی‌های غیرمجاز به متدهای داخلی کلاس‌ها جلوگیری کنید.

۳. ترکیب به جای وراثت (Composition over Inheritance)

وراثت (Inheritance) ابزار قدرتمندی است، اما استفاده بیش از حد از آن باعث ایجاد "زنجیره‌های سفت‌وسخت" (Tight Coupling) می‌شود. در بسیاری از موارد، استفاده از ترکیب (داشتنِ یک شیء داخل شیء دیگر) راه‌حل منعطف‌تری برای گسترشِ کدهای شماست.

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

نکته تکمیلی: اتصال دیرهنگام (Late Binding) 🕰️

چندریختی در جاوا بر پایه مکانیزمی به نام Late Binding یا Dynamic Method Dispatch عمل می‌کند. این یعنی جاوا تا لحظه‌ای که برنامه در حال اجراست (Runtime)، دقیقاً نمی‌داند کدام ورژن از متد را باید اجرا کند. تصمیم‌گیری در لحظه آخر و بر اساس نوعِ "شیئی" که واقعاً در حافظه ساخته شده (نه نوعِ متغیری که به آن اشاره می‌کند) انجام می‌شود. این تفاوت اصلی بین قدرتِ OOP و برنامه‌نویسی سنتی است.

تمرین‌های عملی

برای تثبیت یادگیری این درس تمرین‌های زیر را حل کنید

رفتار متفاوت اشکال Medium
سوال تمرین

کلاس Shape متد draw دارد. کلاس Circle را طوری بسازید که متد draw را بازنویسی کند و متن Draw Circle را چاپ کند.

پاسخ تمرین
JAVA
class Shape {
  public void draw() {
    System.out.println("Draw Shape");
  }
}
class Circle extends Shape {
  @Override
  public void draw() {
    System.out.println("Draw Circle");
  }
}
public class Main {
  public static void main(String[] args) {
    Shape s = new Circle();
    s.draw();
  }
}

آماده رفتن به درس بعدی هستید؟

این درس را به پایان رساندید و می‌توانید به درس بعدی بروید.