مفهوم وراثت (Inheritance) یا ارث بری در php

درسنامه درس 5 از سری شی گرایی در PHP
php-oop-inheritance

با سلام و عرض ادب خدمت شما خواننده ی گرامی؛ با قسمت پنجم (ارث بری در PHP) از سری مباحث آموزش برنامه نویسی شیء گرای PHP در خدمت شما هستیم. تا به اینجا کار با مفاهیم بسیاری آشنا شدیم. از جمله این مفاهیم عبارتند از:

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

در این قسمت قصد داریم وارد مبحث وراثت یا inheritance یا ارث بری در php و برنامه نویسی شیء گرا بشویم. یکی از فواید اصلی برنامه نویسی شیء گرا قابلیت کاهش حجم کد و جلوگیری از code duplication (نوشتن کدهای تکراری) از طریق وراثت است؛ این مشکل زمانی رخ می دهد که یک برنامه نویس، کد مشخصی را بیش از یک بار در سورس کد خود مینویسد.

ارث بری در PHP ( مفهوم Inheritance در PHP)

ما در مبحث ارث بری در php از طرفی یک کلاس پدر با متد ها و خصوصیات خودش را داریم و از طرف دیگر یک کلاس فرزند داریم که میتواند از کدهای پدر استفاده کند. با استفاده از مبحث وراثت میتوان کدی قابل استفاده نوشت که در هر بار استفاده بازیافت می شود و به قولی یک بار مصرف نیست. این مسئله فواید زیادی برای ما دارد:

  • کاهش حجم کد و طبعا بالاتر رفتن سرعت
  • کاهش زمان لازم برای کد نویسی و تکمیل هر پروژه
  • کاهش سردرگمی و گم شدن در زمان ویرایش کدها
  • و الی آخر...

چطور ارث بری در php کار می کند؟

شاید یک عنوان مشابه برای این مبحث بدین صورت باشد: «چگونه یک کلاس ویژگی ها و متدهای کلاس دیگر با ارث می برد؟»

برای اینکه کلاسی، فرزند کلاس دیگری بشود از الگوی (syntax) زیر استفاده می کنیم:

class ChildClassName extends ParentClassName
{
// کدهای کلاس در این قسمت قرار میگیرد
}

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

class Parent {
  // کدهای پدر
}
 
class Child extends Parent {
  // فرزند میتواند از کدهای کلاس پدر استفاده کند
}

نکته ی اول: بدیهی و ساده است که کلاس فرزند برای استفاده از کدهای کلاس پدر، به کلاس پدر نیاز دارد! بنابراین اگر کلاس پدر را در فایلی جداگانه تعریف کرده اید باید آن را قبل از استفاده از کدها، include کنید. از آنجایی که این دوره برای افرادی طراحی شده که با PHP آشنایی پایه دارند از شما انتظار می رود که بدانید این کار توسط دستور require_once انجام می شود.

سوال: چرا require_once و نه include_once یا دستور های دیگر؟

پاسخ: گفتیم که یک کلاسِ فرزند، بدون دسترسی به کدهای پدر نمیتواند کار خود را انجام دهد بنابراین یک "الزام و اجبار" در میان است که همان قسمت require می باشد. از طرفی بعضاً require به تنها می تواند مشکلاتی ایجاد کند چرا که ما فقط یک بار به این کدها نیاز داریم.

نکته ی دوم: وقتی می گوییم "به کدهای کلاس پدر نیاز دارد" در حال کار با مبحث دسترسی (access) هستیم که به نوبه ی خود ما را به سمت access modifier ها هدایت می کند. ما از دستور extends استفاده کرده ایم.

حال آیا فرزند می تواند به تمام کدهای پدر دسترسی داشته باشد؟ خیر! در جلسات قبلی توضیح دادیم که:

  • متد ها یا خصوصیات public توسط همه قابل دسترسی هستند
  • متد ها یا خصوصیات private تنها از داخل خودِ کلاس قابل دسترسی هستند
  • متد ها یا خصوصیات protected تنها توسط فرزند ها یا از داخل خود کلاس قابل دسترسی هستند

بنابراین در حالت private قابل دسترسی نیستند.

نکته ی سوم: کلمه ی extend در فارسی به معنای "گسترش دادن" یا "بسط دادن" است. بنابراین در برنامه نویسی شیء گرا (OOP) میخواهد بگوید فلان کلاسِ فرزند، فلان کلاسِ پدر را گسترش میدهد یا به عبارتی ادامه می دهد. دانستن معنای فارسی این کلمه به درک شما از این مطلب کمک خوبی می کند.

نوبتی هم باشد نوبت یک مثال برای ارث بری در php است! مثال ماشین را از جلسه ی قبل به یاد دارید؟

//کلاس پدر
class Car {
  //  داخل کلاس (private) ویژگی خصوصی
  private $model;
 
  //setter متد عمومی از نوع
  public function setModel($model)
  {
    $this -> model = $model;
  }
 
  public function hello()
  {
    return "beep! I am a <i>" . $this -> model . "</i><br />";
  }
}
 
 
//این کلاس فرزند، کد را از کلاس پدر به ارث می برد
class SportsCar extends Car {
  //هیچ کدی در کلاس فرزند قرار نمیدهیم
}
 
 
//ساخت یک نمونه از کلاس فرزند
$sportsCar1 = new SportsCar();
  
// تعیین مقدار یک خصوصیت در این کلاس
// برای انجام این کار از متدی استفاده می کنیم که در کلاسِ پدر ساخته ایم
$sportsCar1 -> setModel('BMW');
  
//استفاده از متدی دیگر که کلاسِ فرزند آن را از کلاسِ پدر به ارث برده است
echo $sportsCar1 -> hello();

توضیحات اصلی را در خود کد به صورت کامنت گذاشته ام اما یک توضیح کلی نیز میدهم:

ابتدا کلاسی به نام Car (به معنی ماشین) ساختیم و داخل آن یک خصوصیت private و یک متدِ public از نوع setter تعریف کردیم؛ متدِ setModel، مدل ماشین را تعیین کرده و متد hello نیز یک پیام را به ما نمایش میدهد (رجوع کنید به جلسه ی setter ها و getter ها)

حال کلاسی به اسم SportsCar (به معنی ماشینِ اسپرت) تعریف کرده و آن را با دستور extends به عنوان فرزندِ کلاسِ Car معرفی میکنیم. حالا کلاس SportsCar به تمام کدهای public و protected کلاسِ car، دسترسی دارد.

سپس یک نمونه (instance) از کلاس SportsCar میسازیم. توجه کنید که کلاس SportsCar از خود، هیچ کدی ندارد و از کدهای کلاس پدر خود استفاده می کند. اسم نمونه ی ساخته شده را sportsCar1 میگذاریم.

در قسمت بعد مدل sportsCar1 را تعیین می کنیم (BMW) و در آخر از متد hello (که متعلق به پدر است) استفاده کرده تا پیام زیر را به ما نمایش دهد:

beep! I am a BMW

در اول بحث اشاره کردیم که وراثت (inheritance) یا ارث بری در php به ما کمک میکند تا از code duplication جلوگیری کنیم.

آیا بعد از دیدن این مثال متوجه شدید چطور این عمل اتفاق می افتد؟ اگر از مبحث وراثت استفاده نمی کردیم، کلاسِ sportsCar یک کلاس مستقل محسوب می‌شد و نتیجه این بود که باید متد های hello و setModel را دوباره برای آن می نوشتیم!

هر برنامه نویس عاقلی از چنین کاری دوری می‌کند چرا که فریاد اسراف و زیاده نویسی از همه جای آن شنیده می‌شود!

امیدوارم از این قسمت از سری آموزشی ما استفاده ی کامل را برده باشید. در قسمت های بعد بیشتر درباره ی وراثت صحبت خواهیم کرد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری شی گرایی در PHP توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.