برنامه نویسی شی گرا PHP – ضمیمه 3: مفهوم Trait در PHP

درسنامه درس 13 از سری شی گرایی در PHP
php-oop-trait

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

مفهوم Trait ها

یکی از مشکلات زبان برنامه نویسی 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 ها شیء ای بسازید. یک مثال از 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(”); // ‘این مورد را به اشتراک بگذار’

طرز کار trait ها چگونه است؟

همان طور که در مثال قبلی مشاهده کردید، هر دو شیء post و comment دارای متد share بودند در حالی که چنین متدی برایشان تعریف نشده بود. بنابراین trait ها روشی برای copy & paste کد ها در هنگام اجرا هستند. به عبارت دیگر trait مورد نظر هنگام ساخت شیء در کلاس های comment و post کپی شده اند.

تفاوت trait ها و کلاس های انتزاعی چیست؟

trait ها از این نظر با کلاس های انتزاعی هستند که هیچ وابستگی به مبحث وراثت ندارند. تصور کنید که کلاس های post و comment قرار بود از کلاس AbstractSocial ارث بری داشته باشند. قطعا ما در یک شبکه ی اجتماعی کار های بیشتری از کامنت گذاشتن و پست گذاشتن داریم بنابراین شکل کلی وراثت این کلاس ها به شکل پیچیده ی زیر تبدیل می شد:

class AbstractValidate extends AbstractCache {}  
class AbstractSocial extends AbstractValidate {}  
class Post extends AbstractSocial {}

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

تفاوت trait ها و interface ها چیست؟

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()  
{  
//  
}

}

در مثال بالا:

  • یک اینترفیس Sociable داریم که می گوید شیء post می تواند ()Like و ()Share را انجام دهد.
  • یک trait به نام Sharable داریم که متد های ()Like و ()Share را در کلاس post پیاده سازی می کند.

بنابراین همانطور که میبینید شیء 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 ها می رویم و مثال هایی واقعی از استفاده و کاربردشان را ذکر می کنیم.

در پناه حق.

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

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

امیررضا مولودی
11 شهریور 1400
دستتون درد نکنه بسیار عالی بود

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

امیر
03 خرداد 1399
مطالب سایت خیلی رسا ن.شته شده است . تشکر

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

تقی زاده
13 اردیبهشت 1399
با سلام در دو مثال اول غلط املایی وجود دارد. کلمات زیر سرهم نوشته شده و می بایست جدا شوند.(چون در مثال های بعدی جدا نوشته شده اند.) traitSharable useSharable با سپاس از سایت بسیار مفیدتون

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