ارث بری در سی شارپ (Inheritance)

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

ارث بری در سی شارپ (Inheritance)

اصل ارث بری در برنامه نویسی شی گرا (Inheritance Principle)

در سی شارپ، ارث بری به ما اجازه می دهد تا کلاسی جدید از کلاس موجود ایجاد کنیم. این یکی از ویژگی های کلیدی برنامه نویسی شیء گرا (OOP) است .کلاسی که یک کلاس جدید از آن ایجاد می شود به عنوان کلاس پایه ( Super class or Base class) شناخته می شود و کلاس جدید کلاس مشتق شده (Sub class or Drived class) نامیده می شود. کلاس مشتق شده فیلدها و متدهای کلاس پایه را به ارث می برد. این ویژگی به قابلیت استفاده مجدد از کد در برنامه های سی شارپ کمک می کند.

ارث بری فرآیندی است که در آن یک شیء می تواند ویژگی های یک شی دیگر را به دست آورد. وراثت یک نوع رابطه (relationship) است و از مفهوم طبقه بندی پشتیبانی می کند که در آن یک شیء فقط باید آن ویژگی هایی را تعریف کند که آن را در کلاس منحصر به فرد می کند. وراثت شامل یک کلاس پایه و یک کلاس مشتق شده است. کلاس مشتق شده از کلاس پایه ارث می برد و همچنین می تواند اعضای جدیدی را جهت گسترش کلاس پایه اضافه کند.

نوع پایه (base type) بیانگر عمومی سازی یا تعمیم است، در حالی که نوع مشتق شده (derived type) مشخصات یک نمونه را نشان می دهد. به عنوان مثال کارمندانی که می توانند انواع مختلفی داشته باشند مانند کارمند ساعتی، کارمند حقوق بگیر و کارمند موقت. بنابراین در این صورت کارمندان همان general base class و کارمند ساعتی، حقوق بگیر و موقت نیز specialized derived classes محسوب می شوند.

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

ارث بری در زبان برنامه نویسی #C

در سی شارپ از نماد : برای انجام ارث بری استفاده می کنیم. همانطور که در مثال زیر نشان داده شده است.

ارث بری در سی شارپ

در اینجا، کلاس مشتق شده Dog را از کلاس پایه Animal به ارث می بریم. کلاس Dog اکنون می تواند به فیلدها و متدهای کلاس Animal دسترسی داشته باشد.

ارث بری در سی شارپ

مثال زیر نمونه ای از ارث بری در زبان برنامه نویسی سی شارپ را نشان می دهد.

ارث بری در زبان سی شارپ
خروجی قطعه کد بالا در ادامه نشان داده شده است.
خروجی قطعه کد ارث بری

در مثال بالا، کلاس مشتق شده Dog را از کلاس پایه Animal استخراج کرده ایم. به عبارات زیر توجه کنید.

Inheritance in Csharp

در اینجا، از Labrador که object مربوط به کلاس Dog است برای دسترسی به فیلد name و متد ()display کلاس Animal استفاده می کنیم. این عمل امکان پذیر است زیرا کلاس مشتق شده تمام فیلدها و متدهای کلاس پایه را به ارث می برد. همچنین به فیلد name در متد کلاس Dog دسترسی پیدا کرده ایم.

در سی شارپ، وراثت یک رابطه است. ما فقط در صورتی از وراثت استفاده می کنیم که بین دو کلاس رابطه وجود داشته باشد. مثلا:

  • سگ (Dog) یک حیوان (Animal) است.
  • سیب (Apple) یک میوه (Fruit) است.

ما می توانیم Dog را از کلاس Animal و به طور مشابه، سیب (Apple) را از کلاس میوه (Fruit) استخراج کنیم.

اعضای Protected در زبان #C

در سی شارپ، زمانی که یک فیلد یا متد را محافظت شده اعلام می کنیم (سطح دسترسی آن را protected قرار می دهیم)، فقط در همان کلاس و کلاس های مشتق شده از آن قابل دسترسی است.

اعضای محافظت شده در زبان سی شارپ
خروجی قطعه کد بالا در ادامه نشان داده شده است.
اعضای محافظت شده در زبان سی شارپ

در مثال بالا کلاسی به نام Animal ایجاد کرده ایم. کلاس شامل یک متد محافظت شده ()eat است. ما کلاس Dog را از کلاس Animal گرفته ایم. به عبارت ()labrador.eat توجه کنید.

از آنجایی که متد محافظت شده از طریق کلاس های مشتق شده قابل دسترسی است، می توانیم به متد ()eat از کلاس Dog دسترسی پیدا کنیم.

انواع ارث بری

1- Single Inheritance

در Single Inheritance، یک کلاس مشتق شده از یک کلاس پایه واحد ارث می برد. همانطور که در شکل زیر می بینید کلاس B تنها از کلاس پایه A ارث بری می کند.

Single Inheritance

2- Multilevel Inheritance

در Multilevel Inheritance، یا وراثت چندسطحی، یک کلاس مشتق شده از یک کلاس پایه ارث می برد و سپس همان کلاس مشتق شده به عنوان یک کلاس پایه برای کلاس های دیگر عمل می کند. در این حالت کلاس C به صورت غیر مستقیم از طریق کلاس B اعضای کلاس A را نیز به ارث می برد.

ارث بری چند سطحی

3- Hierarchical Inheritance

در Hierarchical Inheritance، یا وراثت سلسله مراتبی، چندین کلاس مشتق شده از یک کلاس پایه واحد ارث می برند.

ارث بری سلسله مراتبی

4- Multiple Inheritance

در Multiple Inheritance، یک کلاس مشتق شده می تواند از چندین کلاس پایه ارث بری کند. نکته ای که وجود دارد این هست که زبان #C از وراثت چندگانه پشتیبانی نمی کند. اما، ما می توانیم از طریق Interface ها به ارث بری چندگانه دست یابیم.

ارث بری چند گانه

5- Hybrid Inheritance

Hybrid Inheritance، یا وراثت ترکیبی، ترکیبی از دو یا چند نوع ارث بری است. ترکیب وراثت چندسطحی و سلسله مراتبی نمونه ای از وراثت ترکیبی است.

ارث بری ترکیبی

قوانین مهم ارث بری در سی شارپ

1- ارث بری سازنده ها (Inheriting Constructors): یک Drived class تمام اعضاء (فیلدها، متدهاو ...) را از Base class خود به ارث می برد. سازنده ها عضو نیستند، بنابراین توسط Drived class ها به ارث نمی رسند. اما سازنده Base class را می توان از Sub class فراخوانی کرد.

2- ارث بری اعضای خصوصی: یک Drived class اعضای خصوصی کلاس والد خود را به ارث نمی برد. با این حال، اگر Base class دارای properties (متدهای set و get ) برای دسترسی به فیلدهای خصوصی خود باشد، یک Drived class می‌تواند ارث بری کند.

کلاس Sealed

کلاس مهر و موم شده (sealed class) در زبان سی شارپ، کلاسی است که توسط هیچ کلاسی به ارث برده نمی شود، اما می توان از آن نمونه ایجاد کرد. هدف طراحی یک کلاس sealed این است که نشان دهد کلاس تخصصی است و نیازی به گسترش آن برای فراهم کردن عملکرد جدید از طریق وراثت برای بازنویسی (override) رفتار آن نیست. یک کلاس مهر و موم شده اغلب برای کپسوله کردن منطقی استفاده می شود که باید در سراسر برنامه استفاده شود اما بدون هیچ تغییری در آن.

کلاس مهر و موم شده بیشتر به دلایل امنیتی ایجاد می شود. به این صورت که از مشتق سازی ناخواسته که از طریق آن، کلاس مشتق شده ممکن است پیاده سازی ارائه شده در کلاس sealed را خراب کند، جلوگیری می کند. برخی از کلاس های کلیدی در کتابخانه .NET framework به منظور محدود کردن توسعه پذیری این کلاس ها به عنوان کلاس های مهر و موم شده طراحی شده اند.

برخلاف ساختار (struct) که به طور ضمنی مهر و موم شده است، یک کلاس مهر و موم شده با کلمه کلیدی "sealed" اعلام می شود تا از ارث بری تصادفی کلاس جلوگیری شود. یک کلاس مهر و موم شده تنها زمانی می تواند مفید باشد که متدهایی با قابلیت دسترسی در سطح عمومی داشته باشد. یک کلاس مهر و موم شده نمی تواند یک کلاس انتزاعی ( abstract class) باشد زیرا یک کلاس انتزاعی کلاسی هست که کامل نیست و اینطور در نظر گرفته شده است که توسط کلاس دیگری مشتق شود که پیاده سازی متد ها و property های انتزاعی را فراهم می کند.

به عنوان مثال، یک کلاس مهر و موم شده، DatabaseHelper، می تواند با ویژگی ها و روش هایی طراحی شود که می تواند عملکردهای اقدامات مرتبط با پایگاه داده، از جمله اتصال باز و بسته پایگاه داده، fetch و به روز رسانی داده ها و غیره را ارائه دهد. از آنجایی که این کلاس عملکردهای حیاتی را انجام می دهد که نباید با بازنویسی در کلاس های مشتق شده آن دستکاری شود، می توان آن را به صورت کلاس مهر و موم شده طراحی کرد.

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

1- کلاس از نوع static است.

2- کلاس شامل اعضای ارثی است که اطلاعات حساس و با اهمیت را نشان می دهد.

3- کلاس برای بازیابی ویژگی های خود از طریق روش reflection پرس و جو می شود.

4- کلاس اعضای مجازی بسیاری را به ارث می برد که باید مهر و موم شوند.

در ادامه نحوه تعریف کلاس sealed نشان داده شده است.

کلاس مهر و موم شده

یک متد نیز می تواند مهر و موم یا sealed شود و در این صورت نمی توان آن متد را بازنویسی کرد. با این حال، یک متد را می توان در کلاس هایی که در آن ها به ارث رسیده است مهر و موم کرد. اگر می خواهید یک متد را به عنوان مهر و موم شده اعلام کنید، باید در کلاس پایه اش (base class) به صورت مجازی (virtual) تعریف شود. در ادامه یک نمونه کلاس مهر و موم شده در سی شارپ ارائه شده است.

Sealed class

خروجی قطعه کد بالا در ادامه نشان داده شده است.
Sealed class output

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

Interfaces

واسط (interface) به عنوان یک قرارداد نحوی تعریف می شود که تمام کلاس هایی که interface را به ارث می برند باید از آن پیروی کنند. interface قسمت "چه چیزی" قرارداد نحوی را تعریف می کند و کلاس های مشتق شده قسمت "چگونه" قرارداد نحوی را تعریف می کنند. interface یک کلاس کاملاً انتزاعی است (abstract class) که فقط می تواند حاوی متدها و ویژگی های انتزاعی باشد (با بدنه های خالی). در ادامه نحوه تعریف interface در سی شارپ نشان داده شده است.

Interfaces در زبان سی شارپ

شروع با حرف "I" در ابتدای یک interface ، تمرین خوبی تلقی می شود، زیرا به کاربر یادآوری می کند که یک interface است و نه یک کلاس. همچنین به طور پیش فرض، اعضای یک interface انتزاعی و عمومی (abstract and public) هستند. interface ها می توانند دارای ویژگی ها و متدها باشند، اما نه فیلدها.

برای دسترسی به متدهای interface ، اینترفیس باید توسط کلاس دیگری که از آن اینترفیس ارث بری کرده "پیاده سازی" شود. برای پیاده سازی یک interface، از نماد : استفاده کنید (درست مانند وراثت). توجه داشته باشید که هنگام پیاده سازی یک interface نیازی به استفاده از کلمه کلیدی override ندارید. مثال زیر را ببینید.

Interfaces

خروجی قطعه کد بالا در ادامه نشان داده شده است.
Interfaces

نکات زیر را در رابطه با interface ها در نظر داشته باشید.

1- مانند کلاس های انتزاعی (abstract classes)، اینترفیس ها را نمی توان برای ایجاد اشیاء استفاده کرد (در مثال بالا، ایجاد یک شی "IAnimal" در کلاس Program امکان پذیر نیست).

2- متدهای interface بدنه ندارند.

3- در پیاده سازی یک interface ، باید همه متد های آن را بازنویسی کنید، به عبارتی کلاسی که از یک اینترفیس ارث بری می کند، باید پیاده سازی هایی را برای متدهای اینترفیس ارائه دهد.

4- interface ها می توانند دارای ویژگی ها و متدها باشند، اما نه فیلدها/متغیرها.

5- اعضای interface به طور پیش فرض abstract و public هستند.

6- یک interface نمی تواند حاوی سازنده باشد (زیرا نمی توان از آن برای ایجاد اشیا استفاده کرد).

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

1- برای دستیابی به امنیت (جزئیات خاص را پنهان کنید و فقط موارد مهم یک شی (interface) را نشان دهید).

2- سی شارپ از "ارث بری چندگانه" یا multiple inheritance پشتیبانی نمی کند (یک کلاس فقط می تواند از یک کلاس پایه ارث بری کند). با این حال، می توان با استفاده از interface ها به این قابلیت دست یافت، زیرا کلاس می تواند چندین interface را پیاده سازی کند. برای پیاده سازی چندین interface باید آن ها را با کاما از هم جدا کنید.

ارث بری در سی شارپ Inheritance انواع ارث بری در c#

مقالات این دسته بندی