در برنامهنویسی شیءگرا، یکی از قابلیتهای بسیار مهم برای طراحی کلاسها، استفاده از کلاسهای abstract است. این کلاسها به شما کمک میکنند ساختاری پایه برای سایر کلاسها ایجاد کنید. به بیان دیگر، کلاسهای abstract به توسعهدهندگان امکان میدهند که الگوی مشترکی برای کلاسهای مختلف تعریف کنند. این نوع کلاسها به توسعهدهندگان امکان میدهد تا طرح کلی از یک کلاس ایجاد کنند که نمیتوان آن را مستقیماً نمونهسازی (instantiate) کرد. به زبان ساده، کلاسهای abstract به عنوان یک الگوی پایه برای ایجاد کلاسهای دیگر عمل میکنند. این مقاله به شما کمک میکند تا با مفهوم کلاسهای abstract در سی شارپ، نحوه استفاده، کاربردهای عملی و مزایای آن آشنا شوید.
در دوره رایگان آموزش سی شارپ شما با مفاهیم اولیه سی شارپ آشنا می شوید.
کلاسهای abstract زمانی مفید هستند که بخواهید اسکلت و ساختاری اولیه برای کلاسهای دیگر تعریف کنید، بدون آنکه امکان استفاده مستقیم از آنها وجود داشته باشد. به عنوان مثال، در یک سیستم مدیریت حیوانات، میتوانید یک کلاس abstract به نام Animal تعریف کنید که متدهایی مانند MakeSound را شامل میشود و کلاسهای فرزند مانند Dog یا Cat آنها را پیادهسازی میکنند. چنین کلاسی میتواند شامل متدها و ویژگیهایی باشد که باید توسط کلاسهای فرزند پیادهسازی شوند، به این ترتیب اطمینان حاصل میشود که تمامی کلاسهای فرزند رفتارهای مشخصی را به اشتراک میگذارند.
در کتاب 'C# 7.0 in a Nutshell'، جوزف آلباهاری در مورد کلاس abstract میگوید: 'کلاس abstract یک ساختار کلی است که میتواند توسط کلاسهای دیگری که از آن ارث بری میکنند، پیادهسازی شود.
در کتاب 'Pro C# 5.0 and the .NET 4.5 Framework'، اندرو ترولسن در مورد استفاده از کلاس abstract میگوید: 'با استفاده از کلاس abstract، میتوانیم ساختار کلیای برای یک مجموعه از کلاسها ایجاد کنیم و از کد تکراری جلوگیری کنیم.
در کتاب 'Essential C# 6.0'، مارک مایکلیس در مورد محدودیتهای کلاس abstract میگوید: 'شما نمیتوانید یک نمونه از یک کلاس abstract ایجاد کنید. این کلاسها باید توسط کلاسهایی که از آنها ارث بری میکنند، پیادهسازی شوند.
کلاس Abstract چیست؟
کلاس abstract یک کلاس پایه است که برای تعریف ویژگیها و رفتارهای مشترک بین کلاسهای فرزند مورد استفاده قرار میگیرد. این کلاسها نمیتوانند مستقیماً نمونهسازی شوند و هدف اصلی آنها فراهمکردن اسکلت اولیه برای کلاسهای فرزند است. کلاس abstract میتواند شامل متدهایی باشد که به صورت کامل پیادهسازی شدهاند و همچنین متدهایی که تنها امضا دارند و باید در کلاسهای فرزند پیادهسازی شوند.
ساختار کلی کلاس Abstract در سی شارپ
برای تعریف یک کلاس abstract در سی شارپ باید از کلمه کلیدی abstract قبل از تعریف کلاس استفاده شود. همچنین میتوان متدهای abstract را نیز تعریف کرد که این متدها در کلاسهای فرزند باید پیادهسازی شوند. کلاسهای abstract برای مواقعی که نیاز به یک طرح اولیه برای کلاسهای دیگر داریم، به کار میروند. به عنوان مثال، در طراحی سیستمهای بانکی، میتوانید یک کلاس abstract به نام Account داشته باشید که شامل متدهایی مانند Withdraw و Deposit باشد و سپس کلاسهای SavingsAccount و CurrentAccount این متدها را پیادهسازی کنند.
استفاده از کلاس abstract
فرض کنید میخواهیم یک برنامه برای مدیریت حیوانات در یک باغوحش بنویسیم. در این باغوحش حیوانات مختلفی وجود دارند مانند اسب، گربه و سگ. همهی این حیوانات دارای ویژگیهای مشترکی هستند مثل خوراکی که میخورند، صدایی که میکنند یا رفتارهای خاصی که دارند. در این صورت، میتوانیم یک کلاس abstract به نام Animal تعریف کنیم و ویژگیهای مشترک در این کلاس قرار دهیم:
public abstract class Animal
{
public abstract string Food { get; }
public abstract string MakeSound() ;
}
حالا کلاسهای Cat, Dog و Horse میتوانند از کلاس Animal ارث بری کنند و ویژگیها و توابع مورد نیاز را پیادهسازی کنند:
public class Cat : Animal
{
public override string Food => "Fish";
public override string MakeSound() => "Meow";
}
کلاسهایی که از کلاسهای abstract ارث بری میکنند و تمام متدهای abstract را پیادهسازی میکنند، به عنوان کلاسهای concrete یا کانکریت شناخته میشوند. این کلاسها قابلیت نمونهسازی دارند و میتوانند برای ایجاد شئ استفاده شوند.
در این مثال، میتوانیم کلاسهای Dog و Horse را به عنوان کلاسهای concrete ایجاد کنیم که از Animal ارث بری میکنند:
public class Dog : Animal
{
public override string Food => "Meat";
public override string MakeSound() => "Woof";
}
public class Horse : Animal
{
public override string Food => "Hay";
public override string MakeSound() => "Neigh";
}
به این ترتیب، میتوانیم یک ساختار کلی برای تمام حیوانات ایجاد کنیم و به ویژگیها و رفتارهای خاص هر حیوان توجه کنیم.
در کل، استفاده از کلاس abstract به ما امکان میدهد تا ساختار کلی برای کلاسهای مشابه بسازیم و به کمک آن، برنامهنویسی را سادهتر و قابل مدیریتتر کنیم.
چرا از کلاس Abstract استفاده کنیم؟
کلاسهای abstract زمانی مفید هستند که بخواهید رفتارهای مشترک را در یک کلاس پایه تعریف کنید و اطمینان حاصل کنید که برخی متدها حتماً توسط کلاسهای فرزند پیادهسازی شوند. این نوع طراحی به شما کمک میکند تا کدتان را به شکل منظمتر و قابل توسعهتری ساختاربندی کنید. استفاده از کلاسهای abstract به معنای طراحی یک الگوی پایه برای کلاسهایی است که قرار است بعداً ایجاد شوند و از مزایای بسیاری برخوردارند.
مزایای استفاده از کلاس Abstract
افزایش خوانایی و نگهداری کد: با استفاده از کلاسهای abstract میتوانید به وضوح تعریف کنید که چه متدهایی باید توسط کلاسهای فرزند پیادهسازی شوند. این کار به خوانایی کد کمک میکند و از بروز خطاهای احتمالی جلوگیری میکند.
کاهش تکرار کد: ویژگیها و متدهای مشترک میتوانند در کلاس پایه تعریف شوند تا دیگر نیازی به تکرار آنها در کلاسهای فرزند نباشد. این امر باعث میشود تا تغییرات به صورت متمرکز انجام شده و بهبودهای کد به سادگی پیادهسازی شوند.
استفاده به عنوان یک الگو: کلاسهای abstract میتوانند به عنوان الگو یا پایهای برای دیگر کلاسها عمل کنند و از این طریق امکان تعریف ساختاری کلی برای کلاسهای مرتبط را فراهم کنند.
تشویق به رعایت اصول SOLID: استفاده از کلاسهای abstract میتواند به برنامهنویسان کمک کند تا اصول SOLID را به خوبی رعایت کنند، خصوصاً اصل Open/Closed که به توسعهدهندگان توصیه میکند کلاسها باید برای توسعه باز و برای تغییر بسته باشند.
تفاوت کلاس Abstract و Interface
یکی از سوالات رایج بین برنامهنویسان، تفاوت بین کلاسهای abstract و interface است. در حالی که هر دو به شما امکان میدهند تا ساختاری برای کلاسها ایجاد کنید، تفاوتهای مهمی بین آنها وجود دارد:
ارثبری (Inheritance): یک کلاس میتواند تنها از یک کلاس abstract ارثبری کند اما میتواند چندین interface را پیادهسازی کند. این ویژگی به شما امکان میدهد تا در استفاده از interfaceها انعطافپذیری بیشتری داشته باشید.
متدهای پیادهسازیشده: در کلاسهای abstract میتوان متدهایی را به صورت کامل پیادهسازی کرد، اما در interface همه متدها باید به صورت abstract باشند (البته با آمدن C# 8.0 امکان تعریف متدهای پیشفرض در interfaceها اضافه شد). این تفاوت به شما اجازه میدهد تا در کلاسهای abstract بخشی از رفتار را مستقیماً تعریف کنید و نیازی به پیادهسازی مجدد در کلاسهای فرزند نباشد.
استفاده از ویژگیها: کلاسهای abstract میتوانند دارای فیلدها و ویژگیهای با دسترسی باشند، در حالی که interface تنها شامل تعریف متدها و ویژگیها است. این موضوع کلاسهای abstract را برای مواقعی که نیاز به دادههای مشترک داریم مناسبتر میکند.
در مقاله تفاوت Abstract و Interface در #C به صورت کامل به این موضوع پرداخته ایم که شما می توانید این مقاله را نیز مطالعه بفرمایید.
بهترین موارد کاربرد کلاسهای Abstract
ایجاد سلسلهمراتب کلاسهای مرتبط: زمانی که کلاسهای فرزند دارای رفتارهای مشترکی هستند که باید به اشتراک گذاشته شوند. برای مثال، در طراحی یک سیستم مدیریت حیوانات، تمامی حیوانات رفتارهایی چون خوردن و حرکتکردن دارند که باید در کلاس پایه تعریف شوند.
پیادهسازی الگوهای طراحی (Design Patterns): بسیاری از الگوهای طراحی، مانند الگوی Template Method، به استفاده از کلاسهای abstract برای پیادهسازی رفتارهای ثابت و متغیر نیاز دارند. این الگو به شما اجازه میدهد که قالب کلی یک الگوریتم را در کلاس abstract تعریف کرده و جزئیات را به کلاسهای فرزند واگذار کنید.
پیشگیری از نمونهسازی غیرضروری: اگر کلاسی نباید مستقیماً نمونهسازی شود و فقط باید به عنوان پایهای برای کلاسهای دیگر مورد استفاده قرار گیرد، abstract کردن آن کلاس میتواند این موضوع را تضمین کند و از نمونهسازی تصادفی جلوگیری کند.
محدودیتهای کلاس abstract
هرچند کلاس abstract قدرتمند و کاربردی است، اما تعدادی محدودیت نیز دارد:
نمیتوان از کلاس abstract نمونهسازی (Instantiate) کرد. یعنی نمیتوان با استفاده از کلیدواژه new یک نمونه از کلاس abstract ایجاد کرد. به عبارت دیگر، کد زیر اشتباه است:
اگر یک کلاس از یک کلاس abstract ارث بری میکند، باید تمامی توابع abstract را پیادهسازی کند. در غیر این صورت، خود باید به عنوان یک کلاس abstract تعریف شود.
یک کلاس نمیتواند از بیش از یک کلاس abstract ارث بری کند. این محدودیت به وراثت یکسان (Single Inheritance) در C# برمیگردد.
مثال کاربردی کلاس abstract
حال فرض کنید میخواهیم یک سیستم برای مدیریت کارمندان در یک شرکت بزرگ طراحی کنیم. در این شرکت، کارمندانی وجود دارند که در بخشهای مختلفی مانند فروش، بازاریابی، مدیریت منابع انسانی و ... کار میکنند. هر یک از این کارمندان وظایف خاص خود را دارند اما تعدادی ویژگی اشتراکی نیز دارند مانند نام، شماره کارمندی، حقوق و ...
در این صورت، میتوانیم از یک کلاس abstract استفاده کنیم تا ویژگیهای اشتراکی کارمندان را در آن تعریف کنیم و سپس برای هر بخش یک کلاس جداگانه تعریف کنیم که از کلاس abstract ارث بری میکند:
public abstract class Employee
{
public string Name { get; set; }
public int EmployeeId { get; set; }
public decimal Salary { get; set; }
public abstract void PerformDuties() ;
}
public class SalesPerson : Employee
{
public override void PerformDuties()
{
// پیادهسازی وظایف خاص فروشنده
}
}
public class HRManager : Employee
{
public override void PerformDuties()
{
// پیادهسازی وظایف خاص مدیر منابع انسانی
}
}
در مثال زیر ، کلاس Animal یک کلاس abstract است که متدی به نام MakeSound دارد که به صورت abstract تعریف شده و باید در کلاس فرزند پیادهسازی شود. همچنین متدی به نام Eat نیز دارد که به صورت کامل تعریف شده و میتواند توسط کلاسهای فرزند به ارث برده شود. این ساختار به کلاس فرزند اجازه میدهد تا برخی از متدها را از کلاس پایه به ارث ببرد و تنها متدهای خاص خود را پیادهسازی کند.
public abstract class Animal
{
public abstract void MakeSound(); // متد انتزاعی که باید در کلاسهای فرزند پیادهسازی شود
public void Eat()
{
Console.WriteLine("This animal is eating.");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof Woof!");
}
}
نتیجهگیری
کلاسهای abstract یکی از ابزارهای قدرتمند در سی شارپ برای طراحی نرمافزارهای قابل توسعه و نگهداری هستند. با استفاده درست از این کلاسها میتوانید از تکرار کد جلوگیری کرده و کلاسهای فرزند را وادار به پیادهسازی رفتارهای مشخصی کنید. اگر به دنبال یک ساختار پایه برای طراحی کلاسهای خود هستید که از ارثبری به خوبی بهرهمند شود، کلاسهای abstract گزینه بسیار خوبی هستند.
کلاسهای abstract به شما کمک میکنند تا اسکلت کلی یک سیستم را تعریف کنید و رفتارهای مشترک را به اشتراک بگذارید، بدون اینکه کلاسهای پایه به طور مستقیم قابل استفاده باشند. استفاده از این نوع کلاسها به وضوح و نگهداری بهتر کد منجر میشود و باعث میشود تا برنامهنویسی به صورت سازماندهیشدهتر انجام شود. همچنین، در پروژههای بزرگ که تعداد زیادی از کلاسهای مشابه و مرتبط وجود دارند، استفاده از کلاسهای abstract به کاهش پیچیدگی و افزایش کارآیی کمک میکند.
برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربریتان شوید