برنامه نویسی شی گرا   

از دانشنامه جوملا فارسی - مامبو فارسی
پرش به: ناوبری، جستجو
Under Construction.png


توجه : این مقاله در حال تکمیل است، لطفاً بعداً برای مطالعه کل آموزش مراجعه نمایید. از ویرایش جزئی در این آموزش خودداری کنید.

برنامه نویسی شی گرا در PHP با رویکرد آموزشی برای جوملا

PHP یک زبان برنامه نویسی شی گراست و همچنین از ساختار MVC برای پیاده سازی جوملا استفاده کرده است. برای توسعه جوملا درک قوی مفاهیم برنام نویسی شی گرا (OOP) لازم است. در این مقاله سعی داریم دلایل استفاده از Objectها و راه‌های استفاده از Objectهایی که PHP از آنها استفاده می‌کند را توضیح دهیم.

این موضوع برای ما به عنوان برنامه نویسی که قصد فراگیری برنامه نویسی شی گرا را داریم، مهم است که دلایل استفاده از شی گرایی را بدانیم.

قبل از شی گرایی تمام برنامه‌ها بر اساس توابع (Function) و متغیرها (Variables) بود. مثلا اگر قرار باشد برنامه محاسبه ارتباط قد و وزن یک شخص BMI را بدون استفاده از شی گرایی بنویسیم به سه متغیر $weight و $height و $name نیاز داریم که برای نگهداری وزن و قد و نام شخص مورد استفاده قرار می‌گیرند. همچنین به یک تابع مثلا calculateBMI() برای محاسبه قد و وزن نیاز داریم که باید پارامترهای $height و $weight را بپذیرد. که به این صورت نوشته می‌شود.


<source lang="php " > function calculateBMI( $height, $weight ) {

   return $weight / $height;

} </source>


مشکل این روش اینست که در صورت تعدد توابع و متغیرها (که عموما در پروژه‌ها به دفعات مجبور به استفاده از آنها هستیم) قادر به تعقیب کد برنامه نخواهیم بود و برنامه نوشته برای سایر افرادی که قصد توسعه آن را داشتند گیج کننده بود. به این نوع کد نویسی برنامه نویسی اسپاگتی می‌گویند از این جهت که خروجی هر تابع ممکن است به عنوان ورودی یا ... در سایر توابع مورد استفاده قرار گیرد که ردیانی کدها را بسیار دشوار می‌سازد.

کلاس class

برای Objectها ایده encapsulate به منظور تغییر در functionها در داخل یک بسته (package) مطرح شد در واقع این بسته همان کلاس(class) می‌باشد. به عنوان مثال پیاده سازی مثال بالا با استفاده از کلاس به صورت زیر خواهد بود :


<source lang="php " > class person {

   var $name;
   var $height;
   var $weight;

   function getBMI() {
       return $this->weight / $this->height;
   }

} </source>


نمونه سازی instantiating

برای استفاده از توابع موجود کلاس‌ها (method) و متغیرهای داخل کلاس، ما باید حتما یک object از نوع آن کلاس ایجاد کنیم. به عنوان مثال اگر شما قصد دارید یک object بسازید که نشان دهنده کلاس person باشد (یعنی با استفاده از آن object بخواهید از متد و متغیرهای داخل کلاس person استفاده کنید) باید به صورت زیر عمل کنید :


<source lang="php " > $person = new person(); </source>

به ایجاد یک object از نوع یک کلاس instantiating می‌گویند چون در واقع یک نمونه instance از آن کلاس است. یک کلاس توسط یک شی مورد دسترسی قرار می‌گیرد.

خصوصیت property

شما با استفاده از objectها میتوانید به مقادیر متغیرهای یک کلاس (properties) را تغییر دهید به این صورت :


<source lang="php " > $person->height = 2; $person->weight = 50; </source>


همچنین شما می‌توانید با استفاده از object توابع (method)ها را فراخوانی کنید :


<source lang="php " > $bmi = $person->getBMI(); </source>


وراثت inheritance

در پروژه‌ها معمولا خیلی از کلاس‌ها شبیه به هم هستند اما مواردی هم وجود دارد که در داخل یک کلاس تفاوت‌های زیادی با دیگر کلاس‌ها وجود دارد به عنوان مثال : هم انسانها و هم حیوانات مثل گربه همگی شٌش دارند برای تنفس. از نظر OOP هر دوی آنها یک متغیر به نام $lung_capacity دارند که بین شان مشترک است ولی گربه دارای دم است که انسانها ندارند پس قاعدتا کلاس حیوانات باید دارای یک متغیر بیشتر به نام $tail_length باشد.

پس در پروژه ما کلاس حیوانات تمام خصوصیات کلاس انسانها را دارد ولی با یکسری خصوصیات بیشتر (دم). به کلاس انسانها Parent و به کلاس حیوانات Child یا Subclass می‌گوییم.

نکته : کلاسهای فرزند (Child) تمام خصوصیات کلاسهای والد (Parent) به علاوه یکسری خصوصیات بیشتر را دارند.

در جوملا اکثر کلاس‌ها فرزند کلاس JObject هستند. یعنی باید تمام خصوصیت‌های کلاس JObject به علاوه یکسری خصوصیات بیشتر را داشته باشند.


<source lang="php " > class person extends JObject {

   var $name;
   var $height;
   var $weight;

   function getBMI() {
       return $this->weight / $this->height;
   }

} </source>


کلاس JObject دارای متدهای ()setو ()getاست که ما با استفاده از این متدها براحتی می‌توانیم کلاس person را تغییر دهیم دقت کنید که ما در کلاس person متدهای ()set و ()getرا نداریم ولی چون کلاس person فرزند کلاس JObject است ما می‌توانیم از متدهای JObject نیز استفاده کنیم. به عمل در شی گرایی وراثت می‌گویند.

وراثت(inheritance) با کلمه کلیدی extends مشخص می شود و الگوی آن در مثال بالا مشخص است.

توجه داشته باشید که $this در داخل کلاسها زیاد استفاده می‌شود در واقع $this به object جاری اشاره می‌کند. بنابراین اگر در داخل یک کلاس از
$this -> height = 2;
استفاده کنیم به این معنی است که خصوصیت height شی جاری برابر 2 ست شده است و وقتی که ما در کد از
$this->height
استفاده می‌کنیم به هیچ عنوان درباره مقدار height صحبت نکرده‌ایم بلکه راجب شی جاری height صحبت کرده‌ایم.

در مورد اشیا (object)ها بیشتر بدانیم

همانطور که گفتیم اشیا object نامیده می‌شوند به این دلیل : اگر در زندگی واقعی یک شی مثل یک دستگاه فتوکپی را تصور کنیم یک رابط خارجی دارد (مانند : یک سینی کاغذ و شیشه دستگاه کپی و صفحه کلید و ...)

متد method

یک کلاس به اسم copier داریم، چه عملیاتی را به طور معمول نیازداریم که برروی copier انجام دهیم؟ یکی از مهم ترین کارهایی که این کلاس باید انجام دهد قابلیت کپی است پس من نیاز به یک متد با قابلیت کپی دارم و اسم آنرا copy می‌گذارم.


<source lang="php " > class Copier {

   function copy() {
       echo 'One copy made';
   }

} </source>


اینک این یک کلاس کپی کننده‌ی کاملا ابتدایی است. به نظر شما چه قابلیت‌ها دیگری برای توسعه این کلاس نیاز داریم‌؟ خوب برای توسعه قابلیت‌های این کلاس باید یک کلاس فرزند از Copier ایجاد کنیم چون کلاس فرزند تمام قابلیت‌های کلاس والد را به ارث می‌برد و یک سری قابلیت‌های دیگر به آن می‌افزاید و این همان چیزی است که ما می‌خواهیم. ما می‌خواهیم یک کلاس کپی دیگری ایجاد کنیم که آن کلاس تعداد کپی‌های گرفته شده را در خود نگه می‌دارد به این منظور به یک property نیاز داریم تا بتواند این خصوصیت (تعداد کپی‌های گرفته شده) را در خود حفظ کند بدین ترتیب که هر زمان کپی جدیدی گرفته شد یک واحد به آن اضافه گردد. کد کلاس فرزند کلاس copier به این صورت است :


<source lang="php " > class CopierWithCounter extends Copier {

   var $counter;

   function copy() {
       $this->counter++;
       parent::copy();
   }

} </source>


اینک ما یک خصوصیت به نام $counter داریم که تعداد کپی‌های گرفته شده در خود نگهداری می‌کند. توجه کنید که در کلاس فرزند (CopierWithCounter) یک متد وجود دارد به نام ()copyیک متد دیگر هم با همین نام در کلاس پدر وجود دارد معنی این کار چیست؟ به کد داخل متد ()copyکلاس فرزند توجه نمایید در یک خط آن داریم


parent::copy();


parent یک کلمه کلیدی در PHP است که به کلاس پدر یا کلاس والد (parent class) اشاره می‌کند که در این مثال به Copier اشاره می‌کند.

بنابراین ما قابلیت مشابه کلاس Copier را داریم با ابن تفاوت که به ازای هر کپی یک واحد به شمارنده اضافه می‌کند.

مقدار دهی اولیه initialize

اگر اقدام به trace کردن این کلاس کرده باشد یک سوال برای شما مطرح می‌شود که مقدار اولیه $counter چقدر است؟ ما فقط می‌دانیم که به این متغیر به ازای هر کپی یک مقدار اضافه می‌شود ولی از مقدار اولیه آن هیچ اطلاعی نداریم. این متغیر نیاز دارد که مقدار دهی اولیه شود (initialize).

عمل مقدار دهی اولیه به متغیرهای کلاس توسط constructor انجام می‌شود. در واقع کار اصلی constructor همین است (مقدار دهی اولیه به متغیرها). constructorها در PHP4.0 توابعی هم نام با کلاس بودند یعنی مثلا اگر اسم کلاس Copy بود اسم constructor یک تابع به نام ()copy می‌شد اما در PHP5.0 کانستراکتور با تابعی به نام

__constructor()

مشخص می‌شود.

ما در جوملا از

__constructor()

استفاده خواهیم کرد. بنابراین کلاس ما به صورت کد زیر تغییر خواهد کرد.


<source lang="php " > class CopierWithCounter extends Copier {

   var $counter;

   function __construct() {
       $this->counter = 0;
   }

   function copy() {
       $this->counter++;
       parent::copy();
   }

} </source>


ما م‌یخواهیم که یک کلاس copier پیشرفته‌تر ایجاد کنیم. می‌خواهیم یک کلاس فرزند دیگر ایجاد کنیم. می‌خواهیم کلاس کپی‌ای ایجاد کنیم که توانایی کپی کردن نسخه متعددی را داشته باشد. ما نیاز به این داریم که مشخص کنیم چقدر کپی می‌خواهیم بگیریم ویک راهی که این تعداد را برای ما نگهداری کنید به این منظور متدی به نام setCopies() را اضافه می‌کنیم.


<source lang="php " > class CopierMultipleCopies extends CopierWithCounter {

   var $copies;

   function setCopies( $copies ) {
       $this->copies = $copies;
   }

} </source>


اینک ما توانستیم مشخص کنیم چه تعداد کپی می‌خواهیم بگیریم.

در شی گرایی مفهومی به نام scope وجود دارد که وقتی ما در مورد scope صحبت می‌کنیم منظورمان محدوده‌ای است که متغیرها می‌توانند دیده و استفاده شوند. به کلاسمان توجه کنید یک property داریم که $copies (متغیر داخل کلاس) نام دارد همچنین در داخل متد setCopies نیز یک پارامتر داریم که $copies (متغیر ورودی به متد) نام دارد.

overriding

اگر یک متد پارامترهایی (متغیر ورودی به متد) داشته باشد مانند $copies در متد بالا. اگر من بخواهم از $copies در داخل آن متد استفاده کنم من باید به آن پارامتر مراجعه کنم ($this) ممکن متغیرهای دیگری در قسمت‌های مختلف کلاس وجود داشته باشند و حتی ممکن است اسم آن متغیرها $copies باشد. آنها برای ما هیچ اهمیتی ندارند اگر من بخواهم به یک property از شی جاری مراجعه کنم باید از کلمه کلیدی $this استفاده کنم. بنا براین اگر از

$this -> copies

استفاده کنیم به منظورما خصوصیت $copies است که به شی جاری تعلق دارد.

متد setCopies یک پارامتر ورودی به نام $copies دارد که در داخل آن شی copiesذخیره می‌شود.

همچنین در کنار متد setCopies میخواهیم تعداد کپی‌های گرفته شده را ذخیره کنیم. توجه داشته باشید که برای کلاس CopierMultipleCopies متد ()copyیا constructor ای تعریف نشده است اما بدلیل extends کردن آن از کلاس CopierWithCounter متد ()copyو propertyهای دیگر را از کلاس CopierWithCounter به ارث میبرد بنابراین بدون انجام هیچ کار اضافه ما یک Copier با شمارنده داریم.

قصد داربم همچنان قابلیت‌های متد ()copyرا که اینک قادر به گرفتن کپی‌های متعدد است توسعه دهیم به این منظور یک متد و یک constructor (که به متغیر ما مقدار اولیه دهد) به کلاسمان اضافه می‌کنیم.


<source lang="php " > class CopierMultipleCopies extends CopierWithCounter {

   var $copies;

   function __construct() {
       $this->copies = 1;
       parent::__construct();
   }

   function setCopies( $copies ) {
       $this->copies = $copies;
   }

   function copy() {
       for ($i = 0; $i < $this->copies; $i++) {
           parent::copy();
       }
   }

} </source>


در این کد ما دقیقا چه کاری انجام دادیم؟ در ابتدا ما یک constructor داریم که به متغیر $copies مقدار اولیه 1 را می‌دهد.

بناراین ما متد ()copyرا override کردیم. در داخل متد ()copyکلاس CopierMultipleCopies یک حلقه تکرار داریم.

در خط اول در داخل حلقه تکرار سه بخش مجزا داریم که با semicolon از هم جدا می‌شوند.

قسمت اول برای مقدار دهی اولیه(intializing) است ما میخواهیم از $i به عنوان شمارنده استفاده کنیم و لازم است که این متغیر بتواند تعداد کپی‌ها را در خود نگهداری پس باید به آن مقدار اولیه اختصاص دهیم و به آن مقدار 0 را اختصاص می‌دهیم.

قسمت دوم مربوط به شرط(condition) است. قبل از انجام هر عملی در حلقه تکرار for این شرط بررسی می‌گردد اگر true بود حلقه تکرار اجرا می‌شوند.

قسمت آخر افزایش دهنده(increamentor). این قسمت پس از هربار اجرای حلقه یکبار اجرا می‌شود.

آن باید به صورت زیر اجرا شود :

  • ساختن یک متغیر و مقدار دهی اولیه آن
  • چک کردن شرط حلقه
  • اجرای دستورات داخل حلقه (ایجاد یک copy)
  • سپس مقدار افزاینده به متغیر اضافه میشود و به مرحله دوم می‌رود.

شما می‌توانید حلقه‌های تکرار به مراتب پیچیده‌تری ایجاد کنید. این حلقه تنها یک نمونه آموزشی است.

حال می‌توانیم از copier استفاده کنیم.ما باید به این منظور از کدهای مانند کدهایی زیر استفاده کنیم :


<source lang="php " > $copier = new CopierMultipleCopies(); $copier->copy(); $copier->copy(); $copier->setCopies( 10 ); $copier->copy(); </source>

Under Construction.png


توجه : این مقاله در حال تکمیل است، لطفاً بعداً برای مطالعه کل آموزش مراجعه نمایید. از ویرایش جزئی در این آموزش خودداری کنید.

منبع : http://docs.joomla.org/Getting_Started_with_Object_Oriented_Programming

ترجمه: شهاب مطاع پور

Indent support.png
هر گونه سوال و یا مشکلی در این رابطه دارید، می‌توانید در انجمن تخصصی تیم جوملا فارسی جستجو کرده و در صورت عدم دریافت نتیجه مورد نظر، سوال جدیدی را مطرح کنید.
8.pngاستفاده از مطالب دانشنامه جوملا فارسی - مامبو فارسی با ذکر منبع ( دانشنامه جوملا فارسی ) و لینک مستقیم به http://docs.joomlafarsi.com بلامانع است.