با سلام و عرض ادب، این مقاله، سومین مقاله از سری ضمیمه های آموزشی برنامه نویسی شیء گرا PHP است. در این قسمت می خواهیم به مبحثی که شباهت زیادی با برخی از مباحث قبلی دارد بپردازیم؛ Trait ها در PHP
یکی از مشکلات زبان برنامه نویسی PHP این است که تنها می توان یک رابطه ی ارث بری داشت و به عبارت دیگر مانند برخی از زبان های برنامه نویسی نمی شود که چندین کلاس از یک کلاس ارث بری داشته باشند. البته باید گفت با اینکه ارث بری چند گانه می تواند مفید باشد (برای مثال می توان از متد های چندین کلاس مختلف استفاده کرد) اما مشکلات خود را نیز دارد؛ برخی اوقات زنجیره ی ارث بری ها آن چنان تو در تو و گم می شود که تشخیص آن ها از هم کار دشواری خواهد بود!
این دو مشکل در PHP 5.4 و با معرفی Trait ها حل شد. این ویژگی به شما اجازه می دهد کلاس های Trait را با کلاسی که از قبل وجود داشته است ترکیب کنید. به این ترتیب هم خوبی های ارث بری چند گانه را خواهیم داشت و هم از مشکلات تو در تو شدن روابط بین کلاس ها دوری می کنیم.
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.
بنابراین اگر بخواهم به طور خلاصه توضیح بدهم می گویم: trait ها به شما اجازه می دهند یک سری از متد ها را در کلاس های مختلفی که ربطی به هم ندارند استفاده کنید.
به زبان ساده Trait ها مجموعه ای از متد ها هستند که شما می خواهید در یک کلاس دیگر از آن ها استفاده کنید. در ضمن، شما، مثل کلاس های انتزاعی، نمیتوانید از خود Trait ها شیء ای بسازید. یک مثال از Trait ها را در کد زیر مشاهده می کنید:
traitSharable { public function share($item) { return ‘sharethisitem’; } }
حالا شما می توانید این trait را در کلاس های دیگر استفاده کنید:
class Post { useSharable; } class Comment { useSharable; }
حالا اگر از این کلاس ها یک نمونه بسازید، می بینید که همه ی این نمونه ها متد ()Share را دارند:
<?php $post = new Post; echo $post->share(”); // ‘این مورد را به اشتراک بگذار’ $comment = new Comment; echo $comment->share(”); // ‘این مورد را به اشتراک بگذار’
همان طور که در مثال قبلی مشاهده کردید، هر دو شیء post و comment دارای متد share بودند در حالی که چنین متدی برایشان تعریف نشده بود. بنابراین trait ها روشی برای copy & paste کد ها در هنگام اجرا هستند. به عبارت دیگر trait مورد نظر هنگام ساخت شیء در کلاس های comment و post کپی شده اند.
trait ها از این نظر با کلاس های انتزاعی هستند که هیچ وابستگی به مبحث وراثت ندارند. تصور کنید که کلاس های post و comment قرار بود از کلاس AbstractSocial ارث بری داشته باشند. قطعا ما در یک شبکه ی اجتماعی کار های بیشتری از کامنت گذاشتن و پست گذاشتن داریم بنابراین شکل کلی وراثت این کلاس ها به شکل پیچیده ی زیر تبدیل می شد:
class AbstractValidate extends AbstractCache {} class AbstractSocial extends AbstractValidate {} class Post extends AbstractSocial {}
همانطور که می بینید این شیوه ی ارث بری بسیار پیچیده و غیر بهینه است به طوری که سر در آوردن از آن موقع توسعه و کد نویسی برای خود دردسر بزرگی محسوب می شود. اما علاوه بر این پیچیدگی ظاهری، اگر ساختار وراثت یک شیء ساده به همین شیوه نباشد، مشکلات بیشتری ایجاد می شود. به طور مثال اگر شیء ای به نام message (به معنی پیام دادن) داشته باشیم که نخواهیم به آن اجازه ی share کردن (اشتراک گذاری) بدهیم، نیاز به یک ساختار وراثت متفاوت داریم!
trait ها و اینترفیس ها شباهت بسیار زیادی به هم دارند؛ هر دو معمولا ساده اند، دقیق هستند و بدون یک کلاس پیاده سازی شده، استفاده ی مستقل و خاصی ندارند. البته تفاوت این دو را باید به خاطر داشته باشیم. اینترفیس مانند قراردادی است که میگوید "این شیء می تواند فلان کار را انجام دهد" در حالی که trait به شیء ما قابلیت انجام هر کاری را می دهد. به طور مثال:
// Interface interface Sociable { public function like(); public function share(); } // Trait trait Sharable { public function share($item) { // share this item } } // Class class Post implements Sociable { use Sharable; public function like() { // } }
در مثال بالا:
بنابراین همانطور که میبینید شیء post اینترفیس sociable را در خود پیاده سازی می کند در حالی که trait نوعی کد با قابلیت استفاده ی مجدد را تعریف می کند که می تواند در کلاس های شبیه نیز قرار بگیرد. مثل:
$post = new Post; if($post instanceOf Sociable) { $post->share(‘hello world’); }
سوال: آیا می توان از چندین trait استفاده کرد؟
پاسخ: بله! باید بین آن ها از ویرگول انگلیسی (comma) استفاده کنید. به مثال زیر دقت کنید:
<?php trait Hello { function sayHello() { echo "Hello"; } } trait World { function sayWorld() { echo "World"; } } class MyWorld { use Hello, World; } $world = new MyWorld(); echo $world->sayHello() . " " . $world->sayWorld(); //Hello World
اگر دقت کنید میبینید که ما در کلاس myWorld از دو trait مختلف استفاده کرده و آن ها را با ویرگول از هم جدا کرده ایم و در آخر خروجی آن رشته ی "Hello World" می باشد!
سوال: اگر چندین trait داشته باشیم چطور؟
پاسخ: در هنگام برنامه نویسی، طبیعی است که به چندین و چند trait برخورد کنیم. PHP برای راحتی کار ما اجازه می دهد trait ها را ادغام کنیم. به مثال زیر توجه کنید:
<?php trait HelloWorld { use Hello, World; } class MyWorld { use HelloWorld; } $world = new MyWorld(); echo $world->sayHello() . " " . $world->sayWorld(); //Hello World
می بینید که از trait های Hello و World (از مثال قبلی) یک trait جداگانه ساختیم!
تا اینجا با مفهوم trait ها آشنا شدیم. در جلسه ی بعدی به سراغ بررسی trait ها می رویم و مثال هایی واقعی از استفاده و کاربردشان را ذکر می کنیم.
در پناه حق.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.