دوره‌ها / JAVA / ارث‌بری (Java Inheritance)

ارث‌بری (Java Inheritance)

15 دقیقه Article

وراثت (Inheritance): قدرتِ انتقال ویژگی‌ها 🧬🏰

وراثت به ما اجازه می‌دهد ویژگی‌ها (Attributes) و متدهای یک کلاس را به کلاس دیگری منتقل کنیم. این کار باعث جلوگیری از تکرار کد و ایجاد یک ساختار درختی (سلسله مراتب) می‌شود.

۱. مفاهیم پایه

  • Subclass (فرزند): کلاسی که از کلاس دیگر ارث می‌برد.
  • Superclass (والد): کلاسی که ویژگی‌هایش به ارث گذاشته می‌شود.

۲. کلمه کلیدی extends 🏹

برای ارث‌بری از extends استفاده می‌کنیم:

{code_block('class Vehicle {\n protected String brand = "Ford";\n public void honk() { System.out.println("Tuut!"); }\n}\n\nclass Car extends Vehicle {\n private String model = "Mustang";\n}')}
protected: اگر فیلدی را protected تعریف کنید، فقط در کلاس‌های والد و فرزند (و همان پکیج) قابل دسترسی است.

۳. کلمه کلیدی final در وراثت

اگر بخواهید مانع شوید که کلاسی به ارث گذاشته شود، از final استفاده کنید:

{code_block('final class SuperSecret { ... }\n// class Child extends SuperSecret { } // خطا! دوباره ارث نمی‌برد')}

چرا از وراثت استفاده می‌کنیم؟

برای ایجاد رابطه "is-a". مثلاً: "ماشین یک وسیله نقلیه است". تمام کدهای مشترک (بوق زدن، حرکت کردن) را در والد می‌نویسیم و کدهای خاص (مدل ماشین) را در فرزند.

نکته فنی: در جاوا، هر کلاس فقط می‌تواند از یک کلاس دیگر ارث ببرد (Multiple Inheritance نداریم). اما نگران نباشید، برای حل این مشکل از Interface استفاده می‌کنیم.
<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) می‌شود. در بسیاری از موارد، استفاده از ترکیب (داشتنِ یک شیء داخل شیء دیگر) راه‌حل منعطف‌تری برای گسترشِ کدهای شماست.

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

نکته تکمیلی: متد سازنده و super 🚀

در مبحث وراثت، وقتی فرزند کلاسی را ارث می‌برد، باید مراقب سازنده‌ها (Constructors) باشید. اگر کلاس والد سازنده‌ای دارد که ورودی می‌گیرد، کلاس فرزند باید با استفاده از کلمه کلیدی super() آن را صدا بزند. این کار باعث می‌شود ابتدا بخش‌های مربوط به والد در حافظه ساخته شوند و سپس کدهای کلاسِ فرزند اجرا شوند. رعایت این سلسله مراتب برای پایداری اشیاء در حافظه الزامی است.

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

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

تعریف فرزند Easy
سوال تمرین

کلاسی به نام Bird با متد fly وجود دارد. کلاسی به نام Parrot بسازید که از Bird ارث ببرد و در متد main شیء آن را ساخته و fly را صدا بزنید.

پاسخ تمرین
JAVA
class Bird {
  public void fly() {
    System.out.println("Flying...");
  }
}
class Parrot extends Bird {
}
public class Main {
  public static void main(String[] args) {
    Parrot p = new Parrot();
    p.fly();
  }
}

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

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