Polymorphism (چند ریختی) در PHP

درسنامه درس 10 از سری شی گرایی در PHP
php-oop-polymorphism

با سلام و عرض ادب،

در این قسمت به سراغ مبحث معروف Polymorphism (واژه ای یونانی به معنی «چند شکلی» یا «چند ریختی») در PHP می رویم. Polymorphism یک قرار داد نام گذاری است که به ما کمک می کند کد های منطقی و با ثبات بنویسیم تا استفاده از آن ها راحت تر شود. بر اساس قانون چند ریختی، متد هایی که در کلاس های مختلف قرار دارند اما کار های یکسان انجام می دهند باید همنام باشند.

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

به طور مثال می توانیم متدی که مساحت را محاسبه می کند (مثل نام آن را ()calcArea که مخفف calculate area است، می گذاریم) صدا زده و در تک تک کلاس هایی که نماینده ی یکی از اشکال هندسی هستند، متدی قرار می دهیم که مساحت را بر اساس شکل آن محاسبه کند. در این حالت هر گاه بخواهیم مساحت شکلی را حساب کنیم، متدی با نام ()calcArea را صدا می زنیم آن هم بدون اینکه نیازی باشد تا به جزئیات فنی مربوط به محاسبه ی تک تک شکل ها توجه زیادی نشان دهیم. تنها چیزی که باید بدانیم نام متدی است که مساحت را حساب می کند.

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

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

برای مطالعه ی این مقاله روی این لینک کلیک کنید.

همچنین برای مطالعه ی مقاله ی مربوط به کلاس های انتزاعی روی این لینک کلید کنید.

در مثال زیر اینترفیسی با نام shape (به معنی شکل) وجود دارد که به تمام کلاس هایی که از آن ارث بری دارند می گوید باید متدی با نام ()calcArea تعریف کنند.

interface Shape {
  public function calcArea();
}

بر همین اساس کلاس circle (به معنی دایره) اینترفیس بالا را در خود پیاده سازی کرده و بنابراین مجبور است متد ()calcArea را با فرمول مخصوص محاسبه ی مساحت دایره بنویسد. اگر از ریاضی دوران دبیرستان و راهنمایی یادتان مانده باشد مساحت دایره به شکل زیر حساب میشد:

شکل 1: مساحت دایره - پلی مورفیسم (چند ریختی) Polymorphism در PHP
شکل 1: مساحت دایره: شعاع به توان 2 ضربدر عدد π که مساوی 3.14 است.

بنابراین:

class Circle implements Shape {
  private $radius;
   
  public function __construct($radius)
  {
    $this -> radius = $radius;
  }
  
  // مساحت دایره را حساب می کند calcArea 
  public function calcArea()
  {
    return $this -> radius * $this -> radius * pi();
  }
}

کلاس rectangle (به معنی مستطیل) نیز از اینترفیس shape استفاده کرده و متد ()calcArea را برای خود اما با همان نام می نویسد:

class Rectangle implements Shape {
  private $width;
  private $height;
   
  public function __construct($width, $height)
  {
    $this -> width = $width;
    $this -> height = $height;
  }
  
  // مساحت دایره را حساب می کند calcArea   
  public function calcArea()
  {
    return $this -> width * $this -> height;
  }
}

یادآوری: آیا یادتان هست که construct__ چه بود؟ در جلسات گذشته به طور خلاصه توضیح دادیم که setter ها به شکل زیر کار می کنند:

class Car {
 
  private $model;
 
  public function setModel($model)
  {
    $this -> model = $model;
  }
 
  public function getModel()
  {
    return "The car model is  " . $this -> model;
  }
}

به عبارت دیگر کار setter ها تغییر مقدار مقادیری است که روی حالت private هستند. و از طرفی گفتیم construct__ نیز به این شکل کار می کند:

class Car{
  private $model;
 
  public function __construct($model)
  {
    $this -> model = $model;
  }
}

به عبارت دیگر construct__ برای خصوصیات شما مقادیر اولیه تعریف می کند و بر همین اساس اگر از چنین کدی (کد بالا) شیء ای ساخته شود:

$car1 = new Car();

با خطای زیر مواجه خواهیم شد:

Warning: Missing argument 1 for Car::__construct()

خطا به این دلیل بود که مقدار اولیه برای شیء ساخته شده تعیین نشد. می توان به construct__ به عنوان یک متد انتزاعی منتها برای خصوصیات (property ها) نگاه کرد.

اگر کد مربوط به construct__ را نمی فهمید یا یادتان رفته است به مقاله ی «مفاهیم Setter ،Getter و Constructor» مراجعه کنید. در قسمت پایانی این مقاله توضیحات مربوط به constructor ها را پیدا خواهید کرد.

حالا می توانیم از کلاس های دایره و مستطیل یک نمونه بسازیم:

$circ = new Circle(3);
$rect = new Rectangle(3,4);

بدین ترتیب تا زمانی که یک کلاس از اینترفیس shape استفاده کند، می توانیم مطمئن باشیم که تمامی اشیاء مساحت را با متد ()calcArea و به طور صحیح (چه مربع باشد، چه مستطیل باشد، چه دایره باشد و غیر آن) محاسبه می کنند.

حالا می توانیم از متد ()calcArea استفاده کنیم تا مساحت اشکال زیر را محاسبه کنیم:

echo $circ -> calcArea();
echo $rect -> calcArea();

خروجی کد ما:

مساحت دایره: 28.274333882308

مساحت مستطیل: 12

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

یا حق

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

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

parvaz
26 اسفند 1400
عالی هستین ممنون از وقتی که میذارین

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

روکسو
12 اردیبهشت 1401
ما هم از شما متشکریم که ما را دنبال می‌کنید.

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

mohsen
23 آبان 1399
عالی توضیح دادین. ممنون

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

اميد
20 شهریور 1399
Polymorphism به اين ميگن كه داخل يك كلاس دو متد هم نام باشند با كار متفاوت.

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

مرصاد
07 خرداد 1399
سلام وعرض خسته نباشید بابت مقاله خوبتون اگه امکانش هست مقاله شی گرایی ++c رو هم به اشراک بزارید

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

Hojat
16 اردیبهشت 1399
هیچوقت, هیچ سایت اموزشی با این نظم و ترتیب ندیده بودم. همه چیز واضح و مشخص. ممنون

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

مسعود
12 مهر 1398
آقا دمت گرم من میخواستم لاراول رو شروع کنم با چیزهایی تو کلاس ها مواجه میشدم که برام آشنا نبود با خوندن این مطالب الان همه چیو درک میکنم

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

امیر زوارمی
14 مهر 1398
سلام دوست عزیز، نظر لطف شماست. خوشحالم که مقاله براتون مفید بوده!

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

ممد نوبریان
14 شهریور 1398
عالیترین سایت در زمینه اموزش برنامه نویسی عالیییی

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

دایره
25 دی 1397
سلام، اینقدر خوب و واضح توضیح دادین که یادم نیست چطور این سایتو پیدا کردم :) تمام قسمت های بخش مفاهیم شئ گرایی در پی اچ پی رو خوندم همین امشب، هرچند تقریبا برای من تکراری بود اما این آموزش به نظرم بهترین آموزشیه که در این زمینه دیدم و به تمام کاربران که میخوان شئ گرایی رو یاد بگیرند توصیه می کنم. در پناه

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

امیر زوارمی
27 دی 1397
سلام نظر لطف شماست! تلاش ما این بوده که مطالب، با بهترین منابع انگلیسی زبان و منابع اصلی چک بشه و طبق برنامه ی آموزشی منظم ارائه بشه. به هر حال خوشحالم که این سری مقالات تونسته به شما کمک کنه، خستگی ما هم در میره وقتی این چیز ها رو میشنویم!

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