تفاوت Interface و Abstract Class چیست؟ یکی از سوالات مهم و پرتکرار در مصاحبه‌های برنامه نویسی، تفاوت Interface و کلاس Abstract است. آشنایی با اینکه چه زمانی از Interface استفاده کنیم؟ و چه زمانی از Abstract Class استفاده کنیم؟ یک قدم شما را برای استخدام شدن نزدیک‌تر می‌کند. در این مقاله از آموزش برنامه نویسی، فرق بین Interface و Abstract Class را بررسی می‌کنیم.

در این مقاله با موضوعات زیر آشنا خواهیم شد:

  • رابط یا Interface چیست؟
  • کلاس انتزاعی یا Abstract Class چیست؟
  • مزایای استفاده از Interface چیست؟
  • مزایای استفاده از Abstract Class چیست؟
  • شباهت Interface و Abstract Class چیست؟
  • تفاوت Interface و Abstract Class چیست؟
  • چه زمانی از Interface استفاده کنیم؟
  • چه زمانی از Abstract Class استفاده کنیم؟

قبل از اینکه به تفاوت اینترفیس (Interface) و کلاس انتزاعی (Abstract Class) بپردازیم، ابتدا باید مفهوم Interface و Abstract Class را بررسی کنیم.

رابط یا Interface چیست؟

Interface چیست؟

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

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

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

<?php

interface Animal {
  public function makeSound();
}

class Cat implements Animal {
  public function makeSound() {
    echo "Meow!";
  }
}

class Dog implements Animal {
  public function makeSound() {
    echo "Woof!";
  }
}

$cat = new Cat();
$cat->makeSound(); //Meow!

$dog = new Dog();
$dog->makeSound(); //Woof!

در کد بالا یک Interface با نام Animal داریم که داخل خود یک متد با نام ()makeSound دارد. دقت کنید که این متد بدنه ندارد و فقط یک اسکلت کلی از متد است. دو کلاس دیگر با نام‌های Cat و Dog داریم که از روی Animal پیاده‌سازی (implements) شده‌اند. چون کلاس Cat و Dog از Animal پیاده‌سازی شده‌اند، حتما باید متدی که داخل اینترفیس Animal وجود دارد، در کلاس Cat و Dog نیز بنویسیم تا با خطا روبرو نشویم.

در کلاس Cat، با استفاده از {} بدنه متد ()makeSound را تعریف می‌کنیم و داخل آن از echo "Meow!" استفاده می‌کنیم. حال یک شیء جدید از کلاس Cat با new کردن می‌سازیم و آن را داخل متغیر cat$ ذخیره می‌کنیم. اکنون متد ()makeSound را صدا می‌کنیم تا گربه صدای "!Meow" بدهد.

در کلاس Dog نیز، با استفاده از {} بدنه متد ()makeSound را تعریف می‌کنیم و داخل آن از echo "Woof!" استفاده می‌کنیم. حال یک شیء جدید از کلاس Dog با new کردن می‌سازیم و آن را داخل متغیر dog$ ذخیره می‌کنیم. حال متد ()makeSound را صدا می‌کنیم تا سگ صدای "!Woof" بدهد.

پس توجه کنید که متد ()makeSound در اینترفیس Animal فقط یک بدنه است که یک صدا دارد. وقتی که از این اینترفیس در کلاس Cat و Dog استفاده می‌کنیم، باید با همان نام باشد و بدنه آن را با {} تعریف کنیم. اما هر کدام را می‌توانیم با صدای خاص خودشان شخصی‌سازی کنیم.

کلاس انتزاعی یا Abstract Class چیست؟

Abstract Class چیست؟

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

بگذارید با یک مثال از دنیای واقعی با مفهوم انتزاع (Abstract) آشنا شویم. کلمه «حیوان» را در نظر بگیرید. آیا با گفتن «حیوان»، حیوان خاصی به نظر شما می‌رسد؟ قطعا پاسخ شما «نه» است چون «حیوان» متعلق به یک موجود خاصی نیست. پس «حیوان» یک انتزاع (Abstract) است چون یک کلمه کلی است و از جزئیات آن اطلاعی نداریم.

اما اگر بگوییم «سگ» یا «گربه» چطور؟ این کلمات کاملا ملموس هستند و از جزئیات آن‌ها خبر داریم. به این اشیاء، واقعی (Concrete) می‌گوییم. در برنامه نویسی نیز، شیءگرایی از دنیای واقعی الهاتم گرفته است. پس نمی‌توانیم از کلاس انتزاعی (Abstract Class) به‌صورت مستقیم نمونه‌سازی کنیم (مثل حیوان). اما می‌توانیم از روی Abstract Class، ارث‌بری کرده و از روی آن اشیاء جدیدی مانند «سگ» یا «گربه» بسازیم.

به مثال زیر توجه کنید:

<?php

abstract class Animal {
  public function walking(){
    echo "The Animal Walks";
  }
}

new Animal(); //Fatal error: Uncaught Error: Cannot instantiate abstract class Animal

در کد بالا یک abstract class با نام Animal تعریف کرده‌ایم که یک متد ()walking برای راه رفتن دارد. در پایین به‌صورت مستقیم یک شیء از کلاس انتزاعی Animal با new کردن ساخته‌ایم که با Fatal error مواجه شده‌ایم چون همانطور که در قسمت بالا گفتیم، نمی‌توان به‌صورت مستقیم از abstract class، شیء ساخت. حال به مثال زیر توجه کنید:

<?php

abstract class Animal {
  public function walking($animalName){
    echo "The " . $animalName . " Walks";
  }
}

class Cat extends Animal {
  //
}

class Dog extends Animal {
  //
}

$myCat = new Cat();
$myCat->walking("Cat"); //The Cat Walks

$myDog = new Dog();
$myDog->walking("Dog"); //The Dog Walks

در کدهای بالا abstract class با نام Animal داریم و دو کلاس با نام‌های Cat و Dog داریم که از کلاس انتزاعی Animal، ارث‌بری (extends) کرده‌اند. سپس در پایین یک نمونه جدید از کلاس Cat و یک نمونه جدید از کلاس Dog با کلمه کلیدی new ایجاد کرده‌ایم. اکنون می‌توانیم از متد ()walking در کلاس انتزاعی Animal، با استفاده از کلاس‌های Cat و Dog استفاده کنیم. چون Cat و Dog از روی Animal ارث‌بری کرده‌اند و می‌توانند از متد آن استفاده کنند.

با استفاده از abstract class دیگر نیازی نیست که متد ()walking را یکبار برای کلاس Cat و یکبار برای کلاس Dog بنویسیم. در حقیقت آن را در کلاس Animal می‌نویسیم چون ویژگی راه رفتن در همه‌ی حیوانات مشترک است. وقتی کلاس‌های Cat و Dog از Animal ارث‌بری کنند، می‌توانند از تمام ویژگی‌های آن بدون دوباره‌نویسی استفاده کنند.

مزایای استفاده از Interface چیست؟

در قسمت بالا دانستیم که اینترفیس چیست؟ در این قسمت با مزایای اینترفیس‌ها آشنا می‌شویم. برخی از مزایای Interfaceها عبارت‌اند از:

  1. افزایش انعطاف‌پذیری: کلاس‌ها قادر به ارتباط با یکدیگر بر اساس قراردادها (Interface) هستند، بدون اینکه وابستگی به جزئیات پیاده‌سازی داشته باشند. این باعث می‌شود که برنامه‌نویسان بتوانند به سادگی تغییراتی در پیاده‌سازی کلاس‌ها ایجاد کنند، بدون آنکه بخش‌های دیگر برنامه تحت تأثیر قرار بگیرند.
  2. جداسازی مسئولیت‌ها: هر Interface، مسئولیت‌ها و قراردادهای خاص خود را تعریف می‌کند و کلاس‌ها بر اساس این قراردادها عمل می‌کنند. این جداسازی به شما امکان می‌دهد تا هر کلاس فقط وظیفه خاص خود را برعهده بگیرد و مسئولیت‌های متفاوت را به طور مستقل مدیریت کنید.
  3. امکان استفاده از پلی‌مورفیسم: شما می‌توانید متدی را با استفاده از Interface تعریف کنید و در هر کلاسی که از این Interface ارث‌بری می‌کند، این متد را با پیاده‌سازی مختلف به صورت متفاوت ایجاد کنید. این امر به شما امکان می‌دهد تا رفتارهای مختلف را در هر کلاس کنترل کنید.
  4. پوشش‌پذیری برای تغییرات آینده: با تعریف قراردادهای (Interface) مناسب، می‌توانید در آینده به راحتی تغییراتی را در کد بدون نیاز به تغییرات گسترده در کلاس‌های مورد استفاده قبلی اعمال کنید.
  5. تشدید قوانین برنامه‌نویسی: با تعیین و اعمال قوانین دقیق در تعریف Interface، می‌توانید برنامه‌نویسان را به رعایت استانداردها و قراردادهای مشخص تشویق کنید. این امر به حفظ یک ساختار مشخص در برنامه کمک می‌کند و باعث می‌شود کدی که با استفاده از Interface نوشته می‌شود، به شکلی قابل‌خوانایی، قابل‌توسعه و قابل‌نگهداری باشد.
  6. امکان تست و شبیه‌سازی ساده‌تر: با تعریف یک Interface مناسب، فرآیند تست و شبیه‌سازی کد بسیار ساده‌تر و موثرتر می‌شود. این امر به شما اجازه می‌دهد تا واحد‌های مختلف کد را به صورت جداگانه تست کنید و تست‌ها را به راحتی با شبیه‌سازی‌ها و مکانیزم‌های دیگر ترکیب کنید.
  7. توسعه‌پذیری و قابلیت‌های بیشتر برای کد: با استفاده از Interface، می‌توانید کد خود را به صورت ماژولار و قابل توسعه طراحی کنید. این امر به شما اجازه می‌دهد که قابلیت‌های جدید را به کد اضافه کنید و تغییرات را به صورت محدود و بدون تأثیر بر سایر قسمت‌های کد اعمال کنید.
  8. ارث‌بری بیشتر: در حالت عادی ارث‌بری از چند کلاس به طور هم زمان امکان پذیر نیست ولی Interface‌ها این مزیت را دارند که به هر تعداد که لازم است، کلاس‌های مشتق‌شده از آن‌ها ارث‌بری کنند.
  9. و...

مزایای استفاده از Abstract Class چیست؟

در قسمت بالا دانستیم که کلاس انتزاعی چیست؟ در این قسمت با مزایای کلاس‌های انتزاعی آشنا می‌شویم. برخی از مزایای Abstract Classها عبارت‌اند از:

  1. ارائه قالب و قواعد عمومی: Abstract Class قادر است قواعد و قالب عمومی را به کلاس‌های فرزند ارائه دهد. این قواعد می‌توانند شامل متدهای پیش‌فرض، متدهای Abstract، متغیرها و روش‌های عمومی باشند. با استفاده از این قالب، از تکرار کدها جلوگیری شده و از ساختار و قواعد مشترک در کلاس‌های فرزند استفاده می‌شود.
  2. پشتیبانی از ارث‌بری چندگانه: Abstract Class به کلاس‌های فرزند اجازه می‌دهد که از یک کلاس پدر ارث‌بری کنند و به عنوان یک پایه برای توسعه و گسترش کلاس‌ها عمل کنند. این قابلیت به شما کمک می‌کند تا از اشتراک کدها، عملکردها و ویژگی‌ها در کلاس‌های مختلف استفاده کنید و کدهای تکراری را به حداقل برسانید.
  3. تعریف متدهای کلاس انتزاعی: Abstract می‌تواند متدهای Abstract (غیرقابل پیاده‌سازی در کلاس اصلی) را تعریف کند. این متدها تنها ساختار و نام دارند و بر عهده کلاس‌های فرزند است که آنها را پیاده‌سازی کنند. این امر به شما اجازه می‌دهد تا یک قرارداد یا قالب کلی را برای کلاس‌های فرزند تعیین کنید و از پیاده‌سازی متدها در کلاس اصلی جلوگیری کنید.
  4. ایجاد محدودیت‌ها و قوانین برای کلاس‌های فرزند: استفاده از Abstract Class به شما این امکان را می‌دهد که محدودیت‌ها و قوانین و ساختار معینی را برای کلاس‌های فرزند تعریف کنید و از رعایت و عملکرد صحیح آن‌ها توسط کلاس‌های فرزند اطمینان حاصل کنید.
  5. و...

شباهت Interface و Abstract Class چیست؟

قبل از اینکه تفاوت Interface و Abstract Class را بررسی کنیم، ابتدا به شباهت Interface و Abstract Class می‌پردازیم. در حقیقت Interface و Abstract Class از لحاظ پنهان‌سازی جزئیات و جلوگیری از کدنویسی دوباره، شبیه هم هستند. هر دوی این‌ها ویژگی‌های مشترک کلاس‌ها را در خود ذخیره می‌کنند. هرجا که بخواهیم می‌توانیم این ویژگی‌های مشترک را در چندین کلاس، بدون دوباره‌نویسی استفاده کنیم.

تفاوت Interface و Abstract Class چیست؟

تفاوت Interface و Abstract Class

در قسمت‌های قبلی با مفاهیم Interface و Abstract Class آشنا شدیم. همچنین مزایای اینترفیس‌ها و کلاس‌های انتزاعی را بررسی کردیم. در این قسمت به مقایسه Interface و Abstract Class می‌پردازیم:

تفاوت Interface و Abstract Class

Interface Abstract Class
Interface چارچوب و قابلیت‌های یک کلاس را مشخص میکند و یک قرارداد است (خودش یک کلاس نیست). Abstract Class یک نوع کلاس را مشخص می‌کند.
اینترفیس‌ها شامل Constant (ثابت) و متدهای انتزاعی (چارچوب کلی متد بدون بدنه) است. کلاس‌های Abstract می‌تواند شامل Constantها، پراپرتی‌ها و متدهای انتزاعی باشد. همچنین می‌تواند شامل متدهای دارای بدنه (متدهای عادی که داخل آن کدنویسی می‌کنیم) باشد.
در Interfaceها، همه‌ی متدها باید public باشند. در Abstract Class، متدها و پراپرتی‌ها می‌توانند هر نوع دسترسی از جمله protected ،public و private باشد.
یک Interface می‌تواند توسط یک Interface دیگر یا یک Abstract Class دیگر توسعه داده شود. یک Abstract Class فقط از یک کلاس معمولی یا یک Abstract Class دیگر می‌تواند توسعه داده شود.
یک Interface تنها می‌تواند از Interface ارث‌بری کند. کلاس Abstract می‌تواند از Interface، کلاس Abstract و یا سایر کلاس‌ها ارث‌بری کند.
وقتی یک Interface توسط یک Interface دیگر توسعه داده شود، لازم نیست متدهای Interface والد در Interface فرزند پیاده‌سازی شود. وقتی یک کلاس عادی، از یک کلاس انتزاعی Extend بشه، کلاس فرزند باید همه متدهای انتزاعی کلاس والد را پیاده‌سازی کند. اما وقتی یک کلاس انتزاعی از یک کلاس انتزاعی دیگر Extend شود، لازم نیست متدهای انتزاعی کلاس والد پیاده‌سازی شود.
یک کلاس یا یک Interface می‌تواند یک یا چند Interface دیگر را پیاده‌سازی کند. یک کلاس می‌تواند فقط و فقط از یک کلاس دیگر Extend (ارث‌بری) کند. مهم نیست کلاس والد، کلاس عادی یا کلاس انتزاعی باشد.
متدهایی که از یک Interface در یک کلاس عادی پیاده‌سازی می‌شوند، باید سطح دسترسی Public داشته باشند. متدهایی که از یک کلاس انتزاعی در یک کلاس دیگر پیاده‌سازی میشوند، می‌توانند سطح دسترسی محدودتری (protected و private) داشته باشند.
به‌صورت مستقیم قابل پیاده‌سازی نیست (new WalletInterface). به‌صورت مستقیم قابل پیاده‌سازی نیست (new AbstractClass).
نمی‌‌تواند شامل متد سازنده (constructor) باشد. می‌‌تواند شامل متد سازنده (constructor) باشد.

چه زمانی از Interface استفاده کنیم؟

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

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

چه زمانی از Abstract Class استفاده کنیم؟

در ادامه مقاله تفاوت Interface و Abstract Class، باید ببینیم که چه زمانی باید از کلاس Abstract استفاده کنیم؟

  1. زمانی که در پروژه‌های بزرگ هستیم و تغییرات زیادی وجود دارند، استفاده از کلاس Abstract بهتر است؛ چون با تغییر Abstract Class، تغییرات به‌طور خودکار در کلاس‌های مشتق شده اعمال می‌شوند.
  2. وقتی که نخواهیم کلیه متد‌ها در کلاس‌های مشتق شده پیاده‌سازی شوند و تعدادی از آن‌ها را در کلاس والد کدنویسی کنیم، باید از کلاس Abstract استفاده کنیم.
  3. به غیر از اعلان متدها و خصوصیت‌ها امکان تعریف عناصر دیگری در Interfaceها وجود ندارد، زمانی که ملزم به استفاده از این عناصر باشیم، استفاده از کلاس‌های Abstract ضروری می‌باشد.
  4. معمولاً از Abstract Class در زمانی استفاده می‌شود که بخواهیم چندین کلاس را با اشتراک ویژگی‌های مشترک ایجاد کنیم و در عین حال می‌خواهیم تعدادی متد از آن را انتزاعی (بدون پیاده‌سازی) تعریف کنیم که در کلاس‌هایی که از آن ارث‌بری می‌کنند، باید پیاده‌سازی شوند.

جمع‌بندی

تفاوت بین Interface و Abstract Class در برنامه نویسی چیست؟ در این مقاله با مفهوم Interface و کلاس Abstract آشنا شدیم. تفاوت بین Interface و کلاس Abstract، یکی از سوالات پرتکرار برنامه نویسی است که دانستن آن برای هر برنامه نویسی ضروری است. اگر سوالی در مورد تفاوت Interface و Abstract Class برای شما گنگ بود، لطفا در قسمت نظرات با ما در میان بگذارید.