وراثت یا ارث بری (Inheritance) یکی از اصول چهارگانه برنامه نویسی شی گرا یا Object Oriented Programming (OOP) است. حتماً مفهوم وراثت را در دنیای واقعی میدانید. رنگ چشم، رنگ مو، قد، نوع مو و خیلی از موارد دیگر بدن ما از والد ما به ارث رسیده است. علاوه بر این که ظاهر و باطن ما بسیار شبیه به والد ما است، خیلی از موارد دیگری وجود دارد که مختص به خودمان است، مثلا علاقه به یک ورزش و یا عرصهای که در آن حرفهای هستیم؛ همچنین اثر انگشت هر یک از ما منحصربهفرد است. در دنیای برنامه نویسی نیز چنین مفهومی وجود دارد.
کلاس جدید میتواند از کلاسهای دیگر ارث بری کند تا رفتار و صفات آن کلاس را به ارث ببرد؛ همچنین این کلاس جدید قادر است ویژگیها و متدهای جدیدی داشته باشد تا دارای ویژگی های منحصربهفرد خود باشد، به عنوان مثال فرض کنید کلاسی داریم با عنوان وسیله نقلیه که شامل متدهای روشن کردن، خاموش کردن، شتاب گرفتن و... است. حال فرض کنید کلاسی وجود داشته باشد با نام کلاس ماشین که از کلاس وسیله نقلیه ارث بری میکند و خاصیتهای جدیدی مانند باز کردن در، بستن در و روشن کردن چراغ در آن تعریف میشود. خود کلاس ماشین که فرزند کلاس وسیله نقلیه است، قادر است تا والد یک کلاس دیگر مثلا بنز شود (به این عمل، ارث بری سلسله مراتبی میگویند). در کلاس بنز که از کلاس ماشین ارث بری میکند مجدداً ویژگیهای جدیدی مانند تنظیم صندلی خودرو، روشن کردن پارک خودکار و... تعریف میشود. کلاسهای دیگری میتوانند از کلاس وسیله نقلیه ارث بری کنند، مانند کلاس موتورسیکلت و کلاس اتوبوس و... . در اصطلاحات برنامهنویسی شی گرا، به کلاس والد، Superclass و به کلاس فرزند، (کلاس مشتق) Subclass میگویند. در بعضی از متون (معمولا قدیمیتر) ممکن است به کلاس والد کلاس Parent و به کلاس فرزند کلاس Child نیز بگویند. شکل زیر نمای UML مثالهای ذکر شده را نشان میدهد:

انواع ارث بری در برنامه نویسی
در برنامهنویسی، انواع ارث بری وجود دارد که در لیست زیر آمده است:
- ارث بری یگانه یا تکی (Single Inheritance)
- ارث بری چندگانه (Multiple Inheritance)
- ارث بری چندسطحی (Multilevel Inheritance)
- ارث بری ترکیبی (Hybrid Inheritance)
بهطور کلی در عمل دو نوع ارث بری وجود دارد؛ اولین نوع ارث بری، تکی یا Single Inheritance میباشد که در آن کلاسها میتوانند تنها از یک کلاس ارث بری کنند. نوع دیگری نیز وجود دارد با نام ارث بری چندگانه یا Multiple Inheritance که کلاس فرزند از چندین کلاس والد ارث بری میکند. انواع چندسطحی و ترکیبی بهصورت تئوری هستند و این گونه نیست که زبان های برنامه نویسی از آنها پشتیبانی کنند یا نکنند. در زبان C++ و پایتون (Python) قادر هستیم تا از Multiple Inheritance استفاده کنیم اما زبانهایی مانند زبان جاوا یا C# دارای این ویژگی نمیباشند و تنها از Single Inheritance پشتیبانی میکنند؛ البته این به معنی محدود بودن زبانهای ذکر شده نمیباشد. در این زبانها ویژگی دیگری با نام اینترفیس (Interface) وجود دارد که میتواند تا حدودی شبیه به ارثبری چندگانه رفتار کند.

مزایا و معایب ارث بری
با این که ارث بری دارای مزایای فراوانی است و کار برنامهنویسان را بسیار راحتتر میکند، اما دارای معایبی نیز میباشد. در این قسمت مهمترین مزایا و معایب ارث بری را بررسی میکنیم.
مزایای ارث بری
- استفاده مجدد از کد (Code Reusability): ارث بری برنامهنویس را قادر میسازد تا از ویژگیهای کلاس والد استفاده مجدد کند و دیگر نیازی به نوشتن دوباره آن در هر کلاس جدید نباشد. به این خاصیت، Reusability کد میگویند.
- ماژولار بودن (Modularity): با استفاده از خاصیت ارث بری میتوان ساختار یک کد را به صورت ماژول (Module) درآورد. به این ترتیب علاوه بر تولید یک ساختار منسجم، عملیات مربوط به رفع باگ و اشکال زدایی (Debugging) راحتتر شده و خاصیتهای جدید میتوانند در قالب ماژول به کد ما اضافه شوند.
- توسعه پذیری کد (Code Extensibility): ارث بری ما را قادر میسازد تا عملکردهای تازه و توابع جدید را به کلاسهای موجود، بدون ایجاد تغییر در کلاسهای والد اضافه کنیم.
معایب ارث بری
- افزایش پیچیدگی: متاسفانه قابلیت ارث بری در بسیاری از موارد باعث پیچیدگی کدمان میشود، به خصوص زمانی که به صورت سلسله مراتبی از ارث بری استفاده میکنیم؛ همچنین ارتباط میان کلاسها میتواند چالشبرانگیز باشد و در بعضی موارد باعث به وجود آمدن باگ در کد شود.
- جفت شدگی (Tight Coupling): یکی از مشکلاتی که برنامهنویسان در بعضی اوقات با آن دست و پنجه نرم میکنند، جفت شدگی یا اتصال کامل است. به این صورت که کلاسها به هم وابستگی شدید پیدا میکنند. در این موارد تغییر در کلاس والد باعث میشود تمامی کلاسهای فرزندان بهطور ناخواسته تحت تاثیر تغییر در کلاس والد قرار گرفته و دچار تغییر شوند بنابراین باید از همان ابتدای کدنویسی بسیار مراقب بود.
- انعطاف ناپذیری (Inflexibility): همانطور که در مورد بالا گفته شد، تغییر در کلاس والد باعث تغییر در تمامی کلاسهای فرزندان میشود بنابراین باید قسمتهای مختلفی از کد را تغییر دهیم. بههمین دلیل خاصیت ارث بری باعث میشود تا کد ما از انعطافپذیری کمتری برخوردار باشد.
ارث بری در کدنویسی
تا اینجا به مفاهیم مربوط به ارث بری پرداختیم. بد نیست که کمی ارث بری را در عمل مشاهده کنیم. در کد زیر که یک کد به زبان پایتون است، کلاس Vehicle ساخته شده است و در آن متد display_brand تعریف شده تا برند وسیله نقلیه را نمایش دهد؛ همچنین کلاس Engine با متد start_engine ایجاد شده است. هردو کلاس Vehicle و Engine، والد کلاس Car هستند. در کلاس Car، متدی با نام display_model ساخته شده است تا مدل ماشین را نمایش دهد. در واقع کلاس Car در اینجا از ویژگی Multiple Inheritance استفاده کرده است:
class Vehicle:
def __init__(self, brand):
self.brand = brand
def display_brand(self):
print("Brand:", self.brand)
class Engine:
def start_engine(self):
print("Engine started.")
class Car(Vehicle, Engine):
def __init__(self, brand, model):
Vehicle.__init__(self, brand)
self.model = model
def display_model(self):
print("Model:", self.model)
my_car = Car("Toyota", "Camry")
my_car.display_brand() # Output: Brand: Toyota
my_car.start_engine() # Output: Engine started.
my_car.display_model() # Output: Model: Camry
همانطور که مشاهده میکنید، در شی ساخته شده از کلاس Car، هر سه تابع ذکر شده را فراخوانی کردیم. کد بالا در زبان ++C بهصورت زیر نوشته میشود:
#include <iostream>
using namespace std;
class Vehicle {
public:
string brand;
Vehicle(string brand) {
this->brand = brand;
}
void displayBrand() {
cout "Brand: " brand endl;
}
};
class Engine {
public:
void startEngine() {
cout "Engine started." model = model;
}
void displayModel() {
cout "Model: " model endl;
}
};
int main() {
Car myCar("Toyota", "Camry");
myCar.displayBrand(); // Output: Brand: Toyota
myCar.startEngine(); // Output: Engine started.
myCar.displayModel(); // Output: Model: Camry
return 0;
}
نمونهی کدهای بالا را نمیتوان در زبانهایی مثل سی شارپ پیادهسازی کرد، چرا که زبان سی شارپ همانطور که گفته شد از ارث بری چندگانه پشتیبانی نمیکند اما میتوان کلاس Engine را بهصورت یک اینترفیس در سی شارپ درآورد و آن اینترفیس را در کلاس Car پیادهسازی یا Implement کرد. در این صورت میتوان از متدهای ایجاد شده در اینترفیس Engine در کلاس Car استفاده نمود. کد زیر این مفهوم را نمایش میدهد:
using System;
interface IEngine
{
void StartEngine();
}
class Vehicle
{
protected string brand;
public Vehicle(string brand)
{
this.brand = brand;
}
public void DisplayBrand()
{
Console.WriteLine("Brand: " + brand);
}
}
class Car : Vehicle, IEngine
{
private string model;
public Car(string brand, string model) : base(brand)
{
this.model = model;
}
public void DisplayModel()
{
Console.WriteLine("Model: " + model);
}
public void StartEngine()
{
Console.WriteLine("Engine started.");
}
}
class Program
{
static void Main(string[] args)
{
Car myCar = new Car("Toyota", "Camry");
myCar.DisplayBrand(); // Output: Brand: Toyota
myCar.DisplayModel(); // Output: Model: Camry
myCar.StartEngine(); // Output: Engine started.
}
}
همانطور که مشاهده میکنید در خط 3، اینترفیسی با نام IEngine تعریف شده است و دارای متد StartEngine میباشد که دقیقاً مانند کلاس Engine در کد پایتون و C++ رفتار میکند.
جمعبندی
ارث بری یکی از مفاهیم پرکاربرد و تقریباً ساده در زمینه برنامهنویسی شی گرا است بنابراین تمامی زبانهای شی گرا دارای این ویژگی میباشند. در این مقاله بهطور جامع به بحث در مورد ویژگی ارث بری پرداخته شد و با مثالهای متعدد سعی کردیم تا درک عمیقتری از مفهوم شی گرایی را در خوانندگان به وجود بیاوریم.
مفهوم ارث بری چیست؟
بهطور خلاصه ارث بری مکانیزمی است که بهوسیله آن، یک کلاس ویژگیها و صفات یک کلاس دیگر را به ارث میبرد و قادر است از آنها استفاده کند همچنین امکان ایجاد متدها و ویژگیهای جدید در کلاس جدید نیز وجود دارد.
آیا ارث بری تنها در زبان های شئ گرا وجود دارد؟
بله، ارث بری یکی از ارکان چهارگانه برنامه نویسی شی گرا است بنابراین اگر زبانی (مانند زبان برنامهنویسی C) از شی گرا پشتیبانی نکند، ارث بری دیگر در آن مفهومی نخواهد داشت.
فرق وراثت یگانه و وراثت چندگانه چیست؟
در وراثت یگانه تنها قادر هستیم تا از یک کلاس ارث بری کنیم؛ اما در وراثت چندگانه میتوانیم از تعداد متعددی از کلاسها ارث بری داشته باشیم. بعضی از زبانها تنها از وراثت یگانه پشتیبانی میکنند؛ مانند زبان های Java و C#، اما زبانهایی مانند Python و C++، علاوه بر وراثت یگانه، از وراثت چندگانه نیز پشتیبانی میکنند.











