انتزاع یا abstraction در شی گرایی
کلاس های abstract مانند کلاس های والد و trait ها، می توانند در عدم تکرار کدها به نحو موثرتری عمل کنند. یک کلاس می تواند از نوع abstract باشد.
کلاس abstract چه کار می کند؟
قبلا گفته ایم که برای جلوگیری از تکرار کدها باید دستورات مشابه را یکجا جمع کنیم و از آن در هر جایی که نیاز داشتیم استفاده کنیم.
فرض کنید قرار است از یک متد چند بار استفاده کنیم در حالی که این متد در بعضی کلاس ها بخش های متفاوتی دارند.
برای این کار از کلاس abstract استفاده می کنیم. متدهایی را در آن تعریف می کنیم که بخش مشترک را پوشش دهند. برای بخش های غیرمشترک باید متدهای اختصاصی در هر کلاس ایجاد کنیم.
با این کار بخش مشترک در کلاس abstract تجمیع شده و مدیریت آن ساده تر می شود و هم چنین از تکرار کدهای مشابه جلوگیری می شود:
class WhiteMilk { public function info() { echo 'Milk-'; echo 'SSO-'; echo 'White'; } } class redMilk { public function info() { echo 'Milk-'; echo 'ESR-'; echo 'red'; } }
مشاهده می کنید که متدهای info در خط اول مشترک هستند ولی از آن به بعد با هم تفاوت دارند.
کلاس abstract به ما کمک می کند که این نقاط مشترک را نیز تجمیع کنیم و در نتیجه کدهای کمتری داشته باشیم.
تعریف کردن کلاس abstract
برای تعریف کردن کلاس abstract باید از کلمه کلیدی abstract استفاده کنیم. سپس کلمه کلیدی abstract را می آوریم و در نهایت نام کلاس را قرار می دهیم.
نام کلاس abstract از قوانین نامگذاری کلاس ها پیروی می کند.
abstract class ClassName { /* ... */ }
abstract class Product { public function show_info() { return $this->product()->company()->color(); } public function product() { echo 'Milk-'; return $this; } protected abstract function company(); protected abstract function color(); } class WhiteMilk extends Product { public function company() { echo 'SSO-'; return $this; } public function color() { echo 'White'; return $this; } } class RedMilk extends Product { public function company() { echo 'ESR-'; return $this; } public function color() { echo 'red'; return $this; } } $object = new WhiteMilk(); $object->show_info(); //output: Milk-SSO-White $object = new RedMilk(); $object->show_info(); //output: Milk-ESR-red
کلاس abstract با کلمه کلیدی abstract آغاز می شود و سپس کلمه کلیدی class می آید و پس از آن نام کلاس قرار می گیرد.
abstract class Product {}
در داخل کلاس abstract، به یک تابع جامع نیاز داریم که کل خروجی را به ما برگرداند.
public function show_info() { return $this->product()->company()->color(); }
برای بخش مشترک نیاز داریم یک متد ایجاد کنیم و دستورات مشترک را درون آن قرار دهیم.
public function product() { echo 'Milk-'; return $this; }
برای بخش های مستقل لازم است متدهای abstract ایجاد کنیم.
protected abstract function company(); protected abstract function color();
این متدهای abstract، نباید هیچ بدنه ای داشته باشند و باید آن ها را در کلاس های خودمان (subclass ها) و بر حسب ویژگی خاص خودشان تعریف کنیم.
اکنون کلاسی که قصد داریم در آن از کلاس abstract استفاده کنیم را از آن extend می کنیم و متدهای ضروری abstract را در هر کدام تعریف می کنیم.
class WhiteMilk extends Product { public function company() { echo 'SSO-'; return $this; } public function color() { echo 'White'; return $this; } } class RedMilk extends Product { public function company() { echo 'ESR-'; return $this; } public function color() { echo 'red'; return $this; } }
برای دسترسی به خروجی نیز کافیست متد اصلی کلاس abstract را با استفاده از آبجکت کلاس فراخوانی می کنیم.
$object = new WhiteMilk(); $object->show_info(); //output: Milk-SSO-White $object = new RedMilk(); $object->show_info(); //output: Milk-ESR-red
ساخت آبجکت از کلاس abstract مجاز نمی باشد و فقط باید کلاس های دیگر را از آن extend کنیم
پس زمانی از کلاس abstract استفاده می کنیم که قرار است برای یک subclass، متدی را بنویسیم و این متد قرار است در subclass دیگر نیز استفاده شود. البته این متدها در همه ی subclass ها به یک شکل نیستند و دارای بخش شخصی نیز می باشند.
متدهای abstract
متدهای abstract بخش ضروری یک کلاس abstract هستند. (گرچه ممکن است بعضی موارد موجود نباشند)
هر subclass که از کلاس abstract ارث برده باشد باید حاوی همه ی متدهای abstract آن کلاس باشد. در واقع یک قاعده ایجاد می کنیم که اگر از کلاس abstract ما extend کردید، باید متدهای abstract این کلاس را نیز فراخوانی کنید.
همچنین هر آرگومان ضروری استفاده شده در متدهای abstract باید در هنگام redeclare آنها در subclass آورده شوند. به علاوه متدهای abstract می توانند حاوی آرگومان های غیرضروری باشند.
کلاس product و متد product هم نام هستند و باعث میشه milk دوبار چاپ بشه
درست میفرمایید