مفاهیم Setter ،Getter و Constructor

درسنامه درس 4 از سری شی گرایی در PHP
php-oop-getter-setter

با قسمت چهارم از سری آموزشی برنامه نویسی شیء گرای PHP در آکادمی روکسو در خدمت شما هستیم. در این قسمت به مفاهیم Setter، Getter و Constructor میپردازیم. اگر تا به حال از IDE های برنامه نویسی استفاده کرده باشید به احتمال زیاد این مفاهیم را به چشم خود دیده اید اما شاید تا امروز در پروژه های خود آنها را بکار نگرفته باشید.

آیا تا به حال فکر کرده اید که آنها به چه دردی میخورند؟ اما قبل از بحث در رابطه با این مفاهیم باید با کلید واژه ی this$ آشنا شوید.

کلید واژه ی this$ چیست؟

this$ (به معنی "این" در فارسی - اشاره به شیء مذکور) برای دسترسی به متدها یا خصوصیت ها در درون یک کلاس استفاده می شود.

الگوی استفاده از این کلید واژه به این صورت است:

$this -> propertyName;

$this -> methodName();

نکته: توجه داشته باشید که در قسمت های قبلی به شما گفتیم که در کنار نامِ خصوصیات و متدها نمی توان از $ استفاده کرد اما کلید واژه ی this$ همیشه این علامت را با خود دارد.

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

class Car {

    // The properties
    public $model;
    public $color = 'black';
    public $hasHorn = true;
 
    public function showCar()
    {
      return "Beep I am a <i>" . $this -> model . "</i>, and I am <i>" .
        $this -> color;
    }
}

نکات در مورد نمونه کد بالا:

  • ارتباط متد ها و خصوصیت ها: در قسمت های قبل متد ها و خصوصیات را طوری تعریف میکردیم که از هم جدا بودند. به عبارت دیگر متد ها و خصوصیت ها در درون یک کلاس قرار داشتند اما با هم (از لحاظ ارجاعات کدنویسی) ارتباطی نداشتند اما اینجا شاهد عکس این مسئله هستیم! حالا با کلید واژه ی this$ میتوانیم بین متد ها و خصوصیات ارتباط برقرار کنیم.
  • عدم وجود $ هنگام ارجاع به یک خصوصیت پس از استفاده از this$

در مثال بالا برای خصوصیت model چیزی تعریف نکردیم بنابراین در این قسمت نتیجه ای نشان داده نمی شود. پس بیایید دانش قسمت های قبلی را با این قسمت ترکیب کنیم و یک شیء جدید از این کلاس Car بسازیم:

$bmw = new Car();

در اینجا فرض کرده ایم که مدل خودروی ما BMW است به همین دلیل اسم شیء را BMW گذاشته ایم. خب حالا که شیء جدیدی از این کلاس ساختیم باید به خصوصیاتش مقدار بدهیم تا با دستورات قبلی چیزی نمایش داده شود:

$bmw -> model = "BMW";
$bmw -> color = "blue";

حالا مقدار خصوصیتِ model برابر با BMW است، اما احتمالا سوالی برای شما پیش آمده؛ ما مقدار color را در خودِ کلاس تعیین کردیم، چطور این عمل را دوباره در خارج از کلاس انجام می دهیم؟ پاسخ ساده است.

به شما گفته بودیم که کلاس ها فقط الگوهایی کلی هستند و نیازی نیست تا اشیاء ساخته ی شده ی ما همگی عیناً شبیه هم باشند. اگر شیء ای که ساخته ایم خصوصیات متفاوتی نسب به خصوصیات کلی کلاس دارد میتوانیم آن را تغییر دهیم.

حالا که مقدار model هم تعیین شد میتوانیم متد showCar را صدا بزنیم تا خروجی را به ما نمایش دهد. خروجی این کد عبارت زیر خواهد بود:

Beep I am a BMW, and I am blue.

توجه کنید که BMW و blue به حالت مُوَرب (italic) نوشته شده اند چرا که در سورس کد از تگ <i> استفاده کرده ایم. اگر نمی دانید تگ <i> چیست به تگ <i> در HTML مراجعه کنید.

سوال: اگر خصوصیتی که تعریف کرده ایم private باشد چطور؟ چطور می توانیم آن را تغییر دهیم؟

پاسخ: این کار مخصوص setter ها (به معنی "تنظیم کننده") و getter ها (به معنی "دریافت کننده") است! نگران نباشید، اینها چیز خاصی نیستند! با یک مثال ساده خدمتتان توضیح میدهم.

همان مثال قبلی و کلاس Car را تصور کنید. اگر خصوصیت model را به صورت private تعریف کنیم چه می شود؟

class Car {

  // مرحله 1
  private $model;

  // مرحله 2 
  public function setModel($model)
  {
    $this -> model = $model;
  }

  // مرحله 3  
  public function getModel()
  {
    return "The car model is  " . $this -> model;
  }
}

توضیحات:

  • مرحله 1: در این قسمت یک خصوصیت به نام model تعریف کردیم و آن را به صورت private قرار دادیم.
  • مرحله 2: در این قسمت یک setter با نام setModel (به معنی "مدل را تعیین کن") ایجاد کردیم. یک متدِ public تعریف کرده ایم (حتما باید public باشد تا بعدا بتوانیم به آن دسترسی داشته باشیم) و داخل آن کد زیر را نوشتیم:

$this -> model = $model;

این کد می گوید مدلِ (model) هر شیء ای (this$) که با این setter تغییر کند برابر با مدلی است که به متد داده شده است؛ یعنی مقداری که داخل پرانتز قرار بگیرد. زمانی که با این کد، مدلِ یک شیء را تغییر بدهیم متوجه می شوید، صبور باشید!

  • مرحله 3: در این قسمت یک getter با نام getModel (به معنی "مدل را دریافت کن") ایجاد کردیم. یک متدِ public تعریف کرده ایم (حتما باید public باشد تا بعدا بتوانیم به آن دسترسی داشته باشیم) و داخل آن کد زیر را نوشتیم:

return "The car model is " . $this -> model;

همانطور که مشخص است getter ها فقط دریافت کننده هستند و هیچ مقداری را تغییر نمی دهند.

این دستور می گوید رشته ی "The car model is " را به مدلِ ماشین بچسبان و به ما تحویل بده (return کن!).

اگر قبلا مقداری برای model ثبت نشده باشد طبیعی است که getter چیزی پیدا نمی کند و با خطا مواجه می شوید.

حالا بیایید کار را عملی کنیم:

$BMW = new Car();
//مرحله 1
$BMW -> setModel("Bayerische Motoren Werke");
//مرحله 2
echo $BMW -> getModel();

توضیحات کد:

ابتدا یک شیء از کلاس Car ساخته و اسم آن را BMW گذاشتیم. سپس،

مرحله 1: با استفاده از متد setter، که قبلا در درونِ خودِ کلاس نوشته بودیم، مقدار آن را برابر با "Bayerische Motoren Werke" قرار می دهیم. این عبارت مخفف نام شرکت BMW است.

مرحله 2: با دستور echo از مدلِ ماشین خروجی گرفته ایم.

اگر از IDE های خوب مانند PHPStorm استفاده می کنید، باید بدانید این IDE ها توانایی ایجاد setter و getter ها را به صورت اتوماتیک برای شما دارند.

مطمئن هستم به همین سادگی با مفاهیم setter و getter آشنا و متوجه شدید که در عین سادگی تا چه حد در کار ما موثر هستند. اگر برای کلاس های خود setter و getter تعریف نکنید باید بدانید دیگر به مقادیر خصوصیات private دسترسی نخواهید داشت. بنابراین قبل از تعریف کلاس باید به این موارد فکر کنید و بر اساس نیاز خود تصمیم بگیرید.

Constructor یا سازنده چیست؟

constructor ها در واقع یکی از چندین متد های جادویی در PHP هستند که از قبل تعریف شده اند. زمانی که یک شیء از یک کلاس خاص ساخته می شود، PHP سریعاً به دنبال متد constructor (در فارسی به معنی "سازنده") می گردد. همانطور که از اسم constructor ها مشخص است کارشان این است که به محض ساخته شدن یک شیء، برای آن مقادیر خصوصیت ها و غیره را می سازند.

نکته ی جالب: در بسیاری از زبان های برنامه نویسی constructor ها به صورت خودکار اسم کلاسشان را برای خود انتخاب می کنند. در PHP 3 و PHP 4 نیز همین گونه بود تا زمانی که PHP 5 وارد عرصه شد و از آنجا به بعد تمامی constructor ها یک نام دارند:
__construct()
"__" که در ابتدای نام آمده است دو عدد آندرلاین است که در ابتدای نام تمامی متد های جادویی در PHP و همچنین ثابت های جادویی می آید.
با این حساب تفاوت constructor و setter ها در چیست؟ به مثال زیر دقت کنید:
class Car{
  private $model;
 
  public function __construct($model)
  {
    $this -> model = $model;
  }
}

اگر چنین کدی داشته باشیم و سپس یک شیء از آن به صورت زیر بسازیم:

$car1 = new Car();

نتیجه خطای زیر خواهد بود:

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

چرا؟ همانطور که گفتیم constructor به محض ساخته شدن شیء می خواهد مقادیر و ویژگی های انتخابی ما را بسازد بنابراین باید به شکل زیر عمل کرد:
$car1 = new Car("BMW");
همانطور که متوجه شدید، یکی از تفاوت های مهم این دو در همین است.
نکته ی مهم: برخلاف setter ها، constructor ها فقط برای ساختن اشیاء از یک کلاس استفاده می شوند بنابراین به هیچ عنوان از return استفاده نمی کنند.

امیدوارم از این قسمت نیز استفاده ی کافی را برده باشید. تا قسمت بعد، در پناه حق.

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

دیدگاه‌های شما (5 دیدگاه)

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

مصطفی
13 آذر 1398
سلام و تشکر از آموزش خوبتون . میخواستم بگم که تقریبا این جمله درست نیست : بنابراین به هیچ عنوان از return استفاده نمی کنند. چون خود متد constructor در پشت صحنه یک return $this در آخرش داره . شما هم میتونید اینو بزارید

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

mohammad
27 آبان 1398
سلام، اولا می خواستم بابت مطالب خوبتون تشکر کنم ثانیا دو سوال داشتم ، سوال اول :تو قسمت setter و getter اگه اون خط که نوشته:private $model رو حذف کنیم باز هم برنامه به درستی کار میکنه،چرا؟ و سوال دوم: تا وقتی میشه همه ی propertyها و همه ی methodهارو به صورت public تعریف کرد چرا باید private تعریف کنیم؟

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

امیر زوارمی
04 آذر 1398
سلام دوست عزیز، قسمت private model خصوصیت یا property ما رو تعریف می کنه. اگر اون رو حذف کنیم کد باز هم اجرا میشه به خاطر اینکه PHP خودش تشخیص میده و به صورت اتوماتیک این کار رو انجام میده براتون اما بهتره همچین کاری نکنید، هم خودتون گیج می شید هم ممکنه باعث مشکلات خاصی بشه. برای استفاده از سطوح دسترسی public و private هم باید بگم بستگی به منطق برنامه تون داره. بعضی از برنامه نویس ها پیشنهاد می کنن به غیر از جاهایی که مطمئن هستید یه چیزی باید به صورت عمومی در دسترس باشه، بقیه رو private کنید تا از دسترسی ناخواسته جلوگیری کنید ولی بعضی ها میگن نیازی به این کار نیست. دعوا سر این موضوع زیاد هست و کلا به اون کد هایی که نوشتین بستگی داره.

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

ممد نوبریان
12 شهریور 1398
بدش نیست

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

فرشید
04 مرداد 1398
با سلام و احترام خدمت استاد گرامی خواستم بگم مطالب سایتتون بسیار جالب ، کامل و واضح هست . من تمام این مطالب رو با هزار زحمت از توی ده ها سایت و کتاب خوندم تا تونستم یه چیزایی ازش سردر بیارم اما الان که سایت شمارو پیداکردم یکباره همه اطلاعات کامل رو یکجا و بصورت کاملا کاربردی دیدم . و حتی باعث شد مطالب پراکنده توی ذهنم شکل درستی بگیرن . خواستم ازتون تشکر و قدردانی کنم بخاطر این حجم از اطلاعات مفید و کامل . به کسانی که میخوان تازه شروع کنن فقط و فقط همین سایت روکسو رو پیشنهاد میکنم . بازم ممنون بخاطر زحمت هاتون .

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

امیر زوارمی
04 مرداد 1398
سلام دوست عزیز، خوشحالم که مورد توجه شما قرار گرفته

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

جواد
10 خرداد 1398
عالی

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

امیر زوارمی
11 خرداد 1398
سلام دوست عزیز، نظر لطف شما است.

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