نیاز به توضیح نیست که طراحان برنامهنویسی شیئگرا (OOP)، از اشیاء دنیای واقعی برای چنین رویکردی در برنامهنویسی الهام گرفتهاند. به عبارتی، همانطور که در دنیای واقعی با اشیاء سروکار داریم، زمانی که اپلیکیشینی را با اصول شیئگرایی مینویسیم نیز با آبجکتها (اشیاء) درگیر هستیم و یکی از ویژگیهایی مربوطه که مبتکرین شیئگرایی از جهان واقعی الهام گرفتهاند، مفهوم Inheritance (وراثت) است. همهٔ ما برخی از خصوصیاتمان را از پدر، پدر بزرگ، دایی و … به ارث میبریم و آن خصیصهها به عنوان بخشی از ذات ما میشوند که به همین صورت در برنامهنویسی شیئگرا از این خصیصه میتوانیم استفاده کنیم. حال برای آنکه به خوبی با مفهوم وراثت در برنامهنویسی، بهخصوص زبان برنامهنویسی پیاچپی آشنا شوید، در این پست سعی خواهیم کرد تا یک مثال در دنیای واقعی را به یک پروژهٔ کوچک تبدیل کنیم.
حیوانات دارای یکسری خصوصیات هستند که مابین آنها مشترک است مثل خوردن، خوابیدن و … اما این در حالی است که برخی حیوانات از خصوصیاتی برخوردارند که سایر حیوانات فاقد آنها هستند (مثلاً مار میتواند نیش بزند اما گنجشک از چنین قابلیتی برخوردار نیست.) در زبان انگلیسی زمانی که بخواهیم حیوانات را به صورت کلی در نظر بگیریم، میتوانیم واژهٔ Animal را مورد استفاده قرار دهیم که از این روی، فایلی ایجاد میکنیم تحت عنوان Animal.php و داخل این فایل کلاسی تعریف میکنیم تحت عنوان Animal که در این صورت خواهیم داشت:
class Animal
{
public $name;
function __construct($input)
{
$this->name = $input;
}
public function eat() {
echo "$this->name is eating";
}
public function sleep() {
echo "$this->name is sleeping";
}
}
در ادامه، قصد داریم تا یک پِراپرتی سراسری برای کلاس خود تعریف کنیم؛ لذا متغیری با نام name$ را داخل این کلاس مینویسیم. حال میخواهیم از یک کانستراکتور در کلاس خود استفاده کنیم تا به محض اینکه آبجکتی از روی این کلاس ساخته شد، دستورات داخل آن اجرا شوند (برای آشنایی بیشتر با مفهوم کانستراکتور، به مقالهٔ آشنایی با مفاهیم Constructor و Destructor در PHP مراجعه نمایید.)
در کدهای بالا به محض ساخت یک آبجکت از روی کلاس Animal، کانستراکتور این کلاس به صورت خودکار اجرا میشود و پارامتر ورودیاش را به متغیر name$ پاس میدهد. در تکمیل کلاس فوق، در ادامه دو متد تعریف کردهایم تحت عناوین ()eat و ()sleep که به ترتیب «خوردن» و «خوابیدن» معنی میدهند و کاری که این متدها انجام میدهند این است که پارامتر ورودی متد کانستراکتور را به عبارات «is eating» و «is sleeping» ضمیمه کرده و در معرض دید کاربر قرار میدهند. در این مرحله از کار، کدهای مرتبط با کلاس Animal به پایان میرسند به طوری که آنچه در این کلاس تعریف کردیم مابین تمامی حیوانات مشترک است. حال قصد داریم تا کلاسی اختصاصی برای گربه ایجاد کنیم که نه تنها دارای خصوصیات مخصوص به خود است، بلکه کلیهٔ خصوصیات کلاس حیوان را نیز اصطلاحاً به ارث برده است:
class Animal
{
public $name;
function __construct($input)
{
$this->name = $input;
}
public function eat() {
echo "$this->name is eating";
}
public function sleep() {
echo "$this->name is sleeping";
}
}
class Cat extends Animal
{
public function meow()
{
echo "$this->name is meowing";
}
}
همانطور که در کد فوق ملاحظه میشود، کلاسی جدید تحت عنوان Cat ایجاد کردهایم و از آنجا که میخواهیم این کلاس کلیهٔ خصوصیات کلاس حیوان را به ارث ببرد، از کلیدواژهٔ extends استفاده کرده سپس نام کلاسی که میخواهیم از آن ارثبری کنیم را نوشتهایم که در این مثال Animal است. از این پس، کلاس Cat دارای کلیهٔ خصوصیات کلاس Animal است که از آن جمله میتوان به «خوردن» و «خوابیدن» اشاره کرد به علاوه اینکه کلاس Cat دارای یک قابلیت منحصر به خود نیز میباشد که «میومیو کردن» است. به عبارت دیگر، داخل کلاس Cat متدی تعریف کردهایم تحت عنوان ()meow که پراپرتی name$ را به عبارت «is meowing» ضمیمه کرده و در معرض دید کاربر قرار میدهد. به همین صورت، کلاس دیگری تحت عنوان Dog ایجاد کرده که از کلاس Animal ارثبری میکند که دارای یک قابلیت منحصر به فرد همچون «واقواق کردن» است:
class Animal
{
public $name;
function __construct($input)
{
$this->name = $input;
}
public function eat()
{
echo "$this->name is eating";
}
public function sleep()
{
echo "$this->name is sleeping";
}
}
class Cat extends Animal
{
public function meow()
{
echo "$this->name is meowing";
}
}
class Dog extends Animal
{
public function bark()
{
echo "$this->name is barking";
}
}
همانطور که در کد فوق ملاحظه میشود، متدی تحت عنوان ()bark ایجاد کرده و پراپرتی name$ را به عنوان خروجی این متد به علاوهٔ عبارت «is barking» در نظر گرفتهایم. برای اینکه خیلی پروژهٔ ما پیچیده نشود، قصد داریم تا آبجکتهای مد نظر خود داخل همین کلاس تعریف کنیم. لذا ابتدا یک آبجکت از روی کلاس Cat ایجاد کرده و متدهای آن را فراخوانی میکنیم:
class Animal
{
public $name;
function __construct($input)
{
$this->name = $input;
}
public function eat()
{
echo "$this->name is eating";
}
public function sleep()
{
echo "$this->name is sleeping";
}
}
class Cat extends Animal
{
public function meow()
{
echo "$this->name is meowing";
}
}
class Dog extends Animal
{
public function bark()
{
echo "$this->name is barking";
}
}
$cat = new Cat('Makhmali');
$cat->eat();
echo '<br>';
$cat->sleep();
echo '<br>';
$cat->meow();
آبجکتی با نام cat$ از روی کلاس Cat ساختهایم و از آنجا که کانستراکتور کلاس Animal نیاز به پارامتر ورودی input$ دارد که قرار است به عنوان «نام» در نظر گرفته شود، نامی همچون «مخملی» را برای گربهٔ خود در نظر گرفتهایم و اینجا است که مفهوم واقعی وراثت در برنامهنویسی را درک خواهیم کرد.
همانطور که در کد فوق ملاحظه میشود، داخل کلاس Cat ما به جزء متدی تحت عنوان ()meow، هیچگونه متد دیگری نداریم اما این در حالی است که متدهایی همچون ()eat و ()sleep را در آبجکت ساخته شده از روی این کلاس فراخوانی کردهایم و علت اینکه ما اجازهٔ چنین کاری را داریم این است که کلاس گربه کلیهٔ قابلیتهای کلاس حیوان را به ارث برده است به طوری که هر قابلیتی موجود در کلاس Animal، در کلاس Cat نیز وجود خواهد داشت؛ به عبارتی، کلاس گربه کلیهٔ ویژگیهای کلاس حیوان را ارثبری کرده است. به همین منوال، میتوان از روی کلاس سگ نیز یک آبجکت ساخت:
class Animal
{
public $name;
function __construct($input)
{
$this->name = $input;
}
public function eat()
{
echo "$this->name is eating";
}
public function sleep()
{
echo "$this->name is sleeping";
}
}
class Cat extends Animal
{
public function meow()
{
echo "$this->name is meowing";
}
}
class Dog extends Animal
{
public function bark()
{
echo "$this->name is barking";
}
}
$cat = new Cat('Makhmali');
$cat->eat();
echo '<br>';
$cat->sleep();
echo '<br>';
$cat->meow();
echo '<br>';
echo '<br>';
$dog = new Dog('Barfi');
$dog->eat();
echo '<br>';
$dog->sleep();
echo '<br>';
$dog->bark();
میبینیم که آبجکتی از روی کلاس سگ ساختهایم با نام dog$ و به عنوان پارامتر ورودی هم نامی همچون «برفی» را در نظر گرفتهایم به طوری که این کلاس هم مانند کلاس گربه، کلیهٔ خصوصیات کلاس حیوان را به ارث برده به علاوه اینکه دارای متد اختصاصی خود با نام ()bark نیز میباشد. توجه داشته باشیم که آبجکت dog$ صرفاً به متدهای کلاس Animal و Dog دسترسی دارد و در صورتی که متد ()meow که به کلاس Cat اختصاص دارد را در آن مورد استفاده قرار دهیم، با ارور مواجه خواهیم شد:
در یک کلام میتوان گفت که استفاده از مفهوم وراثت در کدنویسی، میتواند از دوباره کاری و نوشتن کدهای تکراری به طرز قابلتوجهی جلوگیری کند و نیاز به توضیح نیست که اگر بخواهیم از کدنویسی به صورت Pure PHP به سمت فریمورکهای این زبان همچون لاراول، سیمفونی، زند و غیره مهاجرت کنیم، حتماً نیاز داریم تا با مفهوم Inheritance آشنایی داشته باشیم (چنانچه علاقمند به فراگیری گام به گام زبان برنامهنویسی PHP هستید، میتوانید به دورهٔ آموزش PHP در سکان آکادمی مراجعه نمایید).