برنامه نویسی شی گرا: تفاوت بین نسخه‌ها   

از دانشنامه جوملا فارسی - مامبو فارسی
پرش به: ناوبری، جستجو
(شی Object)
(مطلب نا تمام)
 
(۲ نسخه‌ٔ میانی ویرایش شده توسط ۲ کاربر نشان داده نشده)
سطر ۱: سطر ۱:
=[[برنامه نویسی شی گرا]] در [[PHP]] با رویکرد آموزشی برای [[جوملا]]=
+
{{در حال تکمیل}}
[[PHP]] یک زبان [[برنامه نویسی شی گرا]] ست و همچنین از ساختار MVC برای پیاده سازی [[جوملا]] استفاده کرده است .  برای توسعه جوملا درک قوی مفاهیم  برنام نویسی شی گرا (OOP) لازم است . در این مقاله سعی داریم دلایل استفاده از Objectها و راههای استفاده از Objectهایی که PHP از آنها استفاده میکند را توضیح دهیم .<br />
+
[[رده:کدنویسی و گسترش جوملا ]]
این موضوع برای ما به عنوان برنامه نویسی که قصد  فراگیری برنامه نویسی شی گرا را داریم مهم است که دلایل استفاده از شی گرایی را بدانیم .<br />
+
=برنامه نویسی شی گرا در PHP با رویکرد آموزشی برای جوملا=
قبل از شی گرایی تمام برنامه ها بر اساس توابع (Function) و متغیرها (Variables)  بود . مثلا اگر قرار باشد برنامه محاسبه ارتباط قد و وزن یک شخص BMI یک شخص را بدون استفاده از شی گرایی بنویسیم به سه متغیر $weight و $height و $name نیاز داریم که برای نگهداری وزن و قد و نام شخص مورد استفاده قرار میگیرند . همچنین به یک تابع مثلا calculateBMI() برای محاسبه قد و وزن نیاز داریم که باید پارامترهای $height و $weight را بپذیرد . که به این صورت نوشته میشود.<br />
+
 
 +
[[PHP]] یک زبان برنامه نویسی شی گراست و همچنین از ساختار MVC برای پیاده سازی [[جوملا]] استفاده کرده است.  برای توسعه [[جوملا]] درک قوی مفاهیم  برنام نویسی شی گرا (OOP) لازم است. در این مقاله سعی داریم دلایل استفاده از Objectها و راه‌های استفاده از Objectهایی که [[PHP]] از آنها استفاده می‌کند را توضیح دهیم.
 +
 
 +
این موضوع برای ما به عنوان برنامه نویسی که قصد  فراگیری برنامه نویسی شی گرا را داریم، مهم است که دلایل استفاده از شی گرایی را بدانیم.
 +
 
 +
قبل از شی گرایی تمام برنامه‌ها بر اساس توابع (Function) و متغیرها (Variables)  بود. مثلا اگر قرار باشد برنامه محاسبه ارتباط قد و وزن یک شخص BMI را بدون استفاده از شی گرایی بنویسیم به سه متغیر $weight و $height و $name نیاز داریم که برای نگهداری وزن و قد و نام شخص مورد استفاده قرار می‌گیرند. همچنین به یک تابع مثلا calculateBMI() برای محاسبه قد و وزن نیاز داریم که باید پارامترهای $height و $weight را بپذیرد. که به این صورت نوشته می‌شود.
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
function calculateBMI( $height, $weight ) {
 
function calculateBMI( $height, $weight ) {
سطر ۸: سطر ۱۵:
 
}
 
}
 
</source>
 
</source>
مشکل این روش اینست که در صورت تعدد توابع و متغیرها (که عموما در پروژه ها به دفعات مجبور به استفاده از آنها هستیم) قادر به تعقیب کد برنامه نخواهیم بود و برنامه نوشته برای سایر افرادی که قصد توسعه آن را داشتند گیج کننده بود . به این نوع کد نویسی برنامه نویسی '''اسپاگتی''' میگویند از این جهت که خروجی هر تابع ممکن است به عنوان ورودی یا ... در سایر توابع مورد استفاده قرار گیرد که ردیانی کدها را بسیار دشوار می سازد .<br />
+
 
 +
 
 +
مشکل این روش اینست که در صورت تعدد توابع و متغیرها (که عموما در پروژه‌ها به دفعات مجبور به استفاده از آنها هستیم) قادر به تعقیب کد برنامه نخواهیم بود و برنامه نوشته برای سایر افرادی که قصد توسعه آن را داشتند گیج کننده بود. به این نوع کد نویسی برنامه نویسی '''اسپاگتی''' می‌گویند از این جهت که خروجی هر تابع ممکن است به عنوان ورودی یا ... در سایر توابع مورد استفاده قرار گیرد که ردیانی کدها را بسیار دشوار می‌سازد.
  
 
==کلاس class==
 
==کلاس class==
برای Objectها ایده '''encapsulate''' به منظور تغییر در function ها در داخل یک بسته (package) مطرح شددر واقع این بسته همان کلاس(class)  میباشد. به عنوان مثال پیاده سازی مثال بالا با استفاده از کلاس به صورت زیر خواهد بود :<br />
+
 
 +
برای Objectها ایده '''encapsulate''' به منظور تغییر در functionها در داخل یک بسته (package) مطرح شد در واقع این بسته همان کلاس(class)  می‌باشد. به عنوان مثال پیاده سازی مثال بالا با استفاده از کلاس به صورت زیر خواهد بود :
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class person
 
class person
سطر ۲۴: سطر ۳۶:
 
}
 
}
 
</source>
 
</source>
 +
 +
 
==نمونه سازی instantiating ==
 
==نمونه سازی instantiating ==
برای استفاده از توابع موجود کلاس ها (method) و متغیرهای داخل کلاس , ما باید حتما یک object از نوع آن کلاس ایجاد کنیم . به عنوان مثال اگر شما قصد دارید یک object بسازید که نشان دهنده کلاس person باشد (یعنی با استفاده از آن object بخواهید از متد و متغیرهای داخل کلاس person استفاده کنید) باید به صورت زیر عمل کنید :
+
 
 +
برای استفاده از توابع موجود کلاس‌ها (method) و متغیرهای داخل کلاس، ما باید حتما یک object از نوع آن کلاس ایجاد کنیم. به عنوان مثال اگر شما قصد دارید یک object بسازید که نشان دهنده کلاس person باشد (یعنی با استفاده از آن object بخواهید از متد و متغیرهای داخل کلاس person استفاده کنید) باید به صورت زیر عمل کنید :
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
$person = new person();
 
$person = new person();
 
</source>
 
</source>
به ایجاد یک object از نوع یک کلاس instantiating میگویند چون در واقع یک نمونه instance از آن کلاس است . یک کلاس توسط یک شی مورد دسترسی قرار میگیرد.
+
 
 +
به ایجاد یک object از نوع یک کلاس instantiating می‌گویند چون در واقع یک نمونه instance از آن کلاس است. یک کلاس توسط یک شی مورد دسترسی قرار می‌گیرد.
 +
 
 
==خصوصیت property ==
 
==خصوصیت property ==
شما با استفاده از object ها میتوانید به مقادیر متغیرهای یک کلاس (properties) را تغییر دهید به این صورت :
+
 
 +
شما با استفاده از objectها میتوانید به مقادیر متغیرهای یک کلاس (properties) را تغییر دهید به این صورت :
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
$person->height = 2;
 
$person->height = 2;
 
$person->weight = 50;
 
$person->weight = 50;
 
</source>
 
</source>
همچنین شما میتوانید با استفاده از object توابع (method) ها را فراخوانی کنید :
+
 
 +
 
 +
همچنین شما می‌توانید با استفاده از object توابع (method)ها را فراخوانی کنید :
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
$bmi = $person->getBMI();
 
$bmi = $person->getBMI();
 
</source>
 
</source>
 +
 +
 
==وراثت inheritance==
 
==وراثت inheritance==
در پروژه ها معمولا خیلی از کلاسها شبیه به هم هستند اما مواردی هم وجود دارد که در داخل یک کلاس تفاوتهای زیادی با دیگر کلاسها وجود دارد به عنوان مثال : هم انسانها و هم حیوانات مثل گربه همگی شش دارند برای تنفس . از نظر OOP هر دوی آنها یک متغیر به نام $lung_capacity دارند که بین شان مشترک است ولی گربه دارای دم است که انسانها ندارند پس قاعدتا کلاس حیوانات باید دارای یک متغیر بیشتر به نام $tail_length باشد . پس در پروژه ما کلاس حیوانات تمام خصوصیات کلاس انسانها را دارد ولی با یکسری خصوصیات بیشتر (دم) . به کلاس انسانها '''Parent''' و به کلاس حیوانات '''Child''' یا '''Subclass''' میگوییم.<br />
+
 
نکته : کلاسهای '''فرزند''' (Child) تمام خصوصیات کلاسهای '''والد''' (Parent) را دارند به علاوه یکسری خصوصیات بیشتر.<br />
+
در پروژه‌ها معمولا خیلی از کلاس‌ها شبیه به هم هستند اما مواردی هم وجود دارد که در داخل یک کلاس تفاوت‌های زیادی با دیگر کلاس‌ها وجود دارد به عنوان مثال : هم انسانها و هم حیوانات مثل گربه همگی شٌش دارند برای تنفس. از نظر OOP هر دوی آنها یک متغیر به نام $lung_capacity دارند که بین شان مشترک است ولی گربه دارای دم است که انسانها ندارند پس قاعدتا کلاس حیوانات باید دارای یک متغیر بیشتر به نام $tail_length باشد.
در [[جوملا]] اکثر کلاس ها فرزند کلاس '''JObject''' هستند. یعنی باید تمام خصوصیتهای کلاس JObject را داشته باشند به علاوه یکسری خصوصیات بیشتر.<br />
+
 
 +
پس در پروژه ما کلاس حیوانات تمام خصوصیات کلاس انسانها را دارد ولی با یکسری خصوصیات بیشتر (دم). به کلاس انسانها '''Parent''' و به کلاس حیوانات '''Child''' یا '''Subclass''' می‌گوییم.
 +
 
 +
نکته : کلاسهای '''فرزند''' (Child) تمام خصوصیات کلاسهای '''والد''' (Parent) به علاوه یکسری خصوصیات بیشتر را دارند.
 +
 
 +
در [[جوملا]] اکثر کلاس‌ها فرزند کلاس '''JObject''' هستند. یعنی باید تمام خصوصیت‌های کلاس JObject به علاوه یکسری خصوصیات بیشتر را داشته باشند.
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class person extends JObject
 
class person extends JObject
سطر ۵۶: سطر ۹۱:
 
}
 
}
 
</source>
 
</source>
کلاس JObject دارای متدهای set() و get() است که ما با استفاده از این متدها براحتی میتوانیم کلاس person را تغییر دهیم دقت کنید که ما در کلاس person متدهای set() و get() را نداریم ولی چون کلاس person فرزند کلاس JObject است ما میتوانیم از متدهای JObject نیز استفاده کنیم . به عمل در شی گرایی وراثت میگویند . وراثت(inheritance) با کلمه کلیدی extends مشخص می شود و الگوی آن در مثال بالا مشخص است .<br />
+
 
کلاس JObject دارای متدهای set() و get() است که ما با استفاده از این متدها براحتی میتوانیم کلاس person را تغییر دهیم دقت کنید که ما در کلاس person متدهای set() و get() را نداریم ولی چون کلاس person فرزند کلاس JObject است ما میتوانیم از متدهای JObject نیز استفاده کنیم . به عمل در شی گرایی وراثت میگویند . وراثت(inheritance) با کلمه کلیدی '''extends''' مشخص می شود و الگوی آن در مثال بالا مشخص است .
+
 
<br />
+
کلاس JObject دارای متدهای ()setو ()getاست که ما با استفاده از این متدها براحتی می‌توانیم کلاس person را تغییر دهیم دقت کنید که ما در کلاس person متدهای ()set و ()getرا نداریم ولی چون کلاس person فرزند کلاس JObject است ما می‌توانیم از متدهای JObject نیز استفاده کنیم. به عمل در شی گرایی وراثت می‌گویند.  
توجه داشته باشید که $this در داخل کلاسها زیاد استفاده میشود در واقع $this به object جاری اشاره میکند . بنابراین اگر در داخل یک کلاس از <div dir=ltr>$this -> height = 2;  </div>  استفاده کنیم به این معنی است که خصوصیت height شی جاری برابر 2 ست شده است و وقتی که ما در کد از  <div dir=ltr>$this->height</div> استفاده میکنیم به هیچ عنوان درباره مقدار height صحبت نکرده ایم بلکه راجب شی جاری height صحبت کرده ایم .<br />
+
 
 +
وراثت(inheritance) با کلمه کلیدی extends مشخص می شود و الگوی آن در مثال بالا مشخص است.
 +
 
 +
توجه داشته باشید که $this در داخل کلاسها زیاد استفاده می‌شود در واقع $this به object جاری اشاره می‌کند. بنابراین اگر در داخل یک کلاس از <div dir=ltr>$this -> height = 2;  </div>  استفاده کنیم به این معنی است که خصوصیت height شی جاری برابر 2 ست شده است و وقتی که ما در کد از  <div dir=ltr>$this->height</div> استفاده می‌کنیم به هیچ عنوان درباره مقدار height صحبت نکرده‌ایم بلکه راجب شی جاری height صحبت کرده‌ایم.
 +
 
 
==در مورد اشیا (object)ها بیشتر بدانیم ==
 
==در مورد اشیا (object)ها بیشتر بدانیم ==
همانطور که گفتیم اشیا object نامیده میشوند به این دلیل : اگر در زندگی واقعی یک شی مثل یک دستگاه فتوکپی را تصور کنیم یک رابط خارجی دارد (مانند : یک سینی کاغذ و شیشه دستگاه کپی و صفحه کلید و ...) <br />
+
 
 +
همانطور که گفتیم اشیا object نامیده می‌شوند به این دلیل : اگر در زندگی واقعی یک شی مثل یک دستگاه فتوکپی را تصور کنیم یک رابط خارجی دارد (مانند : یک سینی کاغذ و شیشه دستگاه کپی و صفحه کلید و ...)  
 +
 
 
== متد method==
 
== متد method==
یک کلاس به اسم copier داریم , چه عملیاتی را به طور معمول نیازداریم که برروی copier انجام دهیم ؟ یکی از مهم ترین کارهایی که این کلاس باید انجام دهد قابلیت کپی است پس من نیاز به یک متد با قابلیت کپی دارم و اسم آنرا copy میگذارم .
+
 
 +
یک کلاس به اسم copier داریم، چه عملیاتی را به طور معمول نیازداریم که برروی copier انجام دهیم؟ یکی از مهم ترین کارهایی که این کلاس باید انجام دهد قابلیت کپی است پس من نیاز به یک متد با قابلیت کپی دارم و اسم آنرا copy می‌گذارم.
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class Copier
 
class Copier
سطر ۷۲: سطر ۱۱۶:
 
}
 
}
 
</source>
 
</source>
اینک این یک کلاس کپی کننده ی کاملا ابتدایی است . به نظر شما چه قابلیتها دیگری برای توسعه این کلاس نیاز داریم ؟ خوب برای توسعه قابلیتهای این کلاس باید یک کلاس فرزند از Copier ایجاد کنیم چون کلاس فرزند تمام قابلیتهای کلاس والد را به ارث میبرد و یک سری قابلیتهای دیگر به آن میافزاید و این همان چیزی است که ما میخواهیم . ما میخواهیم یک کلاس کپی دیگری ایجاد کنیم که آن کلاس تعداد کپی های گرفته شده را در خود نگه میدارد به این منظور به یک property  نیاز داریم تا بتواند این خصوصیت (تعداد کپی های گرفته شده) را در خود حفظ کند بدین ترتیب که هرزمان کپی جدیدی گرفته شد یک واحد به آن اضافه گردد. کد کلاس فرزند کلاس copier به این صورت است :
+
 
 +
 
 +
اینک این یک کلاس کپی کننده‌ی کاملا ابتدایی است. به نظر شما چه قابلیت‌ها دیگری برای توسعه این کلاس نیاز داریم‌؟ خوب برای توسعه قابلیت‌های این کلاس باید یک کلاس فرزند از Copier ایجاد کنیم چون کلاس فرزند تمام قابلیت‌های کلاس والد را به ارث می‌برد و یک سری قابلیت‌های دیگر به آن می‌افزاید و این همان چیزی است که ما می‌خواهیم. ما می‌خواهیم یک کلاس کپی دیگری ایجاد کنیم که آن کلاس تعداد کپی‌های گرفته شده را در خود نگه می‌دارد به این منظور به یک property  نیاز داریم تا بتواند این خصوصیت (تعداد کپی‌های گرفته شده) را در خود حفظ کند بدین ترتیب که هر زمان کپی جدیدی گرفته شد یک واحد به آن اضافه گردد. کد کلاس فرزند کلاس copier به این صورت است :
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class CopierWithCounter extends Copier
 
class CopierWithCounter extends Copier
سطر ۸۴: سطر ۱۳۲:
 
}
 
}
 
</source>
 
</source>
اینک ما یک خصوصیت به نام $counter داریم که تعداد کپی های گرفته شده در خود نگهداری میکند. توجه کنید که در کلاس فرزند (CopierWithCounter) یک متد وجود دارد به نام copy() یک متد دیگر هم با همین نام در کلاس پدر وجود دارد معنی این کار چیست ؟ به کد داخل متد copy() کلاس فرزند توجه نمایید در یک خط آن داریم  
+
 
 +
 
 +
اینک ما یک خصوصیت به نام $counter داریم که تعداد کپی‌های گرفته شده در خود نگهداری می‌کند. توجه کنید که در کلاس فرزند (CopierWithCounter) یک متد وجود دارد به نام ()copyیک متد دیگر هم با همین نام در کلاس پدر وجود دارد معنی این کار چیست؟ به کد داخل متد ()copyکلاس فرزند توجه نمایید در یک خط آن داریم  
 +
 
 +
 
 
<div dir=ltr>parent::copy(); </div>
 
<div dir=ltr>parent::copy(); </div>
parent یک کلمه کلیدی در [[PHP]] است که به کلاس پدر یا کلاس والد (parent class) اشاره میکند که در این مثال به Copier اشاره میکند.
+
 
<br />
+
 
بنابراین ما قابلیت مشابه کلاس Copier را داریم با ابن تفاوت که به ازای هر کپی یک واحد به شمارنده اضافه میکند.  
+
parent یک کلمه کلیدی در [[PHP]] است که به کلاس پدر یا کلاس والد (parent class) اشاره می‌کند که در این مثال به Copier اشاره می‌کند.
<br />
+
 
 +
بنابراین ما قابلیت مشابه کلاس Copier را داریم با ابن تفاوت که به ازای هر کپی یک واحد به شمارنده اضافه می‌کند.  
 +
 
 
==مقدار دهی اولیه initialize==
 
==مقدار دهی اولیه initialize==
اگر اقدام به trace کردن این کلاس کرده باشد یک سوال برای شما مطرح میشود که مقدار اولیه $counter چقدر است ؟ ما فقط میدانیم که به این متغیر به ازای هر کپی یک مقدار اضافه میشود ولی از مقدار اولیه آن هیچ اطلاعی نداریم . این متغیر نیاز دارد که مقدار دهی اولیه شود (initialize) .
+
 
<br />
+
اگر اقدام به trace کردن این کلاس کرده باشد یک سوال برای شما مطرح می‌شود که مقدار اولیه $counter چقدر است؟ ما فقط می‌دانیم که به این متغیر به ازای هر کپی یک مقدار اضافه می‌شود ولی از مقدار اولیه آن هیچ اطلاعی نداریم. این متغیر نیاز دارد که مقدار دهی اولیه شود (initialize).
عمل مقدار دهی اولیه به متغیرهای کلاس توسط '''constructor''' انجام میشود . در واقع کار اصلی constructor همین است (مقدار دهی اولیه به متغیرها). constructorها در PHP4.0  توابعی هم نام با کلاس بودند یعنی مثلا اگر اسم کلاس Copy بود اسم constructor یک تابع به نام copy() میشد اما در PHP5.0 کانستراکتور با تابعی به نام
+
 
 +
عمل مقدار دهی اولیه به متغیرهای کلاس توسط '''constructor''' انجام می‌شود. در واقع کار اصلی constructor همین است (مقدار دهی اولیه به متغیرها). constructorها در [[PHP]]4.0  توابعی هم نام با کلاس بودند یعنی مثلا اگر اسم کلاس Copy بود اسم constructor یک تابع به نام ()copy می‌شد اما در [[PHP]]5.0 کانستراکتور با تابعی به نام
 +
 
 
<div dir=ltr>__constructor()</div>
 
<div dir=ltr>__constructor()</div>
مشخص میشود. ما در [[جوملا]] و ادامه این آموزش نیز از
+
 
 +
مشخص می‌شود.
 +
 
 +
ما در [[جوملا]] از  
 +
 
 
<div dir=ltr>__constructor()</div>
 
<div dir=ltr>__constructor()</div>
استفاده خواهیم کرد. بنابراین کلاس ما به صورت کد زیر تغییر خواهد کرد .
+
 
 +
استفاده خواهیم کرد. بنابراین کلاس ما به صورت کد زیر تغییر خواهد کرد.
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class CopierWithCounter extends Copier
 
class CopierWithCounter extends Copier
سطر ۱۱۳: سطر ۱۷۶:
 
}
 
}
 
</source>
 
</source>
ما میخواهیم که یک کلاس copier پیشرفته تر ایجاد کنیم . میخواهیم یک کلاس فرزند دیگر ایجاد کنیم . میخواهیم کلاس کپی ای ایجاد کنیم که توانایی کپی کردن نسخه متعددی را داشته باشد . ما نیاز به این داریم که مشخص کنیم چقدر کپی میخواهیم بگیریم ویک راهی که این تعداد را برای ما نگهداری کنید به این منظور متدی به نام setCopies() را اضافه میکنیم .
+
 
 +
 
 +
ما م‌یخواهیم که یک کلاس copier پیشرفته‌تر ایجاد کنیم. می‌خواهیم یک کلاس فرزند دیگر ایجاد کنیم. می‌خواهیم کلاس کپی‌ای ایجاد کنیم که توانایی کپی کردن نسخه متعددی را داشته باشد. ما نیاز به این داریم که مشخص کنیم چقدر کپی می‌خواهیم بگیریم ویک راهی که این تعداد را برای ما نگهداری کنید به این منظور متدی به نام setCopies() را اضافه می‌کنیم.
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class CopierMultipleCopies extends CopierWithCounter
 
class CopierMultipleCopies extends CopierWithCounter
سطر ۱۲۴: سطر ۱۹۱:
 
}
 
}
 
</source>
 
</source>
اینک ما توانستیم مشخص کنیم چه تعداد کپی میخواهیم بگیریم .
+
 
<br />
+
 
در شی گرایی مفهومی به نام '''scope''' وجود دارد که وقتی ما در مورد scope صحبت میکنیم منظورمان محدوده ای است که متغیرها میتوانند دیده و استفاده شوند . به '''کلاسمان''' توجه کنید یک property داریم که $copies (متغیر داخل کلاس) نام دارد همچنین در داخل '''متد''' setCopies نیز یک پارامتر داریم که $copies (متغیر ورودی به متد) نام دارد .
+
اینک ما توانستیم مشخص کنیم چه تعداد کپی می‌خواهیم بگیریم.
<br />
+
 
 +
در شی گرایی مفهومی به نام '''scope''' وجود دارد که وقتی ما در مورد scope صحبت می‌کنیم منظورمان محدوده‌ای است که متغیرها می‌توانند دیده و استفاده شوند. به '''کلاسمان''' توجه کنید یک property داریم که $copies (متغیر داخل کلاس) نام دارد همچنین در داخل '''متد''' setCopies نیز یک پارامتر داریم که $copies (متغیر ورودی به متد) نام دارد.
 +
 
 
==overriding==
 
==overriding==
اگر یک متد پارامترهایی (متغیر ورودی به متد) داشته باشد مانند $copies در متدبالا . اگر من بخواهم از $copies در داخل آن متد استفاده کنم من باید به آن پارامتر مراجعه کنم ($this) ممکن متغیرهای دیگری در قسمت های مختلف کلاس وجود داشته باشند و حتی ممکن است اسم آن متغیرها $copies باشد. آنها برای ما هیچ اهمیتی ندارند اگر من بخواهم به یک property از شی جاری مراجعه کنم باید از کلمه کلیدی $this استفاده کنم . بنا براین اگر از  
+
 
 +
اگر یک متد پارامترهایی (متغیر ورودی به متد) داشته باشد مانند $copies در متد بالا. اگر من بخواهم از $copies در داخل آن متد استفاده کنم من باید به آن پارامتر مراجعه کنم ($this) ممکن متغیرهای دیگری در قسمت‌های مختلف کلاس وجود داشته باشند و حتی ممکن است اسم آن متغیرها $copies باشد. آنها برای ما هیچ اهمیتی ندارند اگر من بخواهم به یک property از شی جاری مراجعه کنم باید از کلمه کلیدی $this استفاده کنم. بنا براین اگر از  
 +
 
 
<div dir=ltr> $this -> copies </div>
 
<div dir=ltr> $this -> copies </div>
 +
 
استفاده کنیم به منظورما خصوصیت $copies  است که به شی جاری تعلق دارد.
 
استفاده کنیم به منظورما خصوصیت $copies  است که به شی جاری تعلق دارد.
<br />
+
 
متد setCopies یک پارامتر ورودی به نام $copies دارد که در داخل آن شی copiesذخیره میشود.  
+
متد setCopies یک پارامتر ورودی به نام $copies دارد که در داخل آن شی copiesذخیره می‌شود.  
<br />
+
 
همچنین در کنار متد setCopies میخواهیم تعداد کپی های گرفته شده را ذخیره کنیم . توجه داشته باشید که برای کلاس CopierMultipleCopies متد copy() یا constructor ای تعریف نشده است اما بدلیل extends کردن آن از کلاس CopierWithCounter متد copy() و propertyهای دیگر را از کلاس CopierWithCounter به ارث میبرد بنابراین بدون انجام هیچ کار اضافه ما یک Copier با شمارنده داریم .
+
همچنین در کنار متد setCopies میخواهیم تعداد کپی‌های گرفته شده را ذخیره کنیم. توجه داشته باشید که برای کلاس CopierMultipleCopies متد ()copyیا constructor ای تعریف نشده است اما بدلیل extends کردن آن از کلاس CopierWithCounter متد ()copyو propertyهای دیگر را از کلاس CopierWithCounter به ارث میبرد بنابراین بدون انجام هیچ کار اضافه ما یک Copier با شمارنده داریم.
<br />
+
 
قصد داربم همچنان قابلیتهای متد copy() را که اینک قادر به گرفتن کپی های متعدد است توسعه دهیم به این منظور یک متد و یک constructor (که به متغیر ما مقدار اولیه دهد) به کلاسمان اضافه میکنیم .
+
قصد داربم همچنان قابلیت‌های متد ()copyرا که اینک قادر به گرفتن کپی‌های متعدد است توسعه دهیم به این منظور یک متد و یک constructor (که به متغیر ما مقدار اولیه دهد) به کلاسمان اضافه می‌کنیم.
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
class CopierMultipleCopies extends CopierWithCounter
 
class CopierMultipleCopies extends CopierWithCounter
سطر ۱۵۹: سطر ۲۳۳:
 
}
 
}
 
</source>
 
</source>
در این کد ما دقیقا چه کاری انجام دادیم ؟ در ابتدا ما یک constructor داریم که به متغیر $copies مقدار اولیه 1  را میدهد . بعد ....
+
 
<br />
+
 
بناراین ما متد copy() را override کردیم . در داخل متد copy() کلاس CopierMultipleCopies یک حلقه تکرار داریم .
+
در این کد ما دقیقا چه کاری انجام دادیم؟ در ابتدا ما یک constructor داریم که به متغیر $copies مقدار اولیه 1  را می‌دهد.  
<br />
+
 
در خط اول در داخل حلقه تکرار سه بخش مجزا داریم که با semicolon از هم جدا میشوند .
+
بناراین ما متد ()copyرا override کردیم. در داخل متد ()copyکلاس CopierMultipleCopies یک حلقه تکرار داریم.
<br />
+
 
قسمت اول برای مقدار دهی اولیه(intializing) است ما میخواهیم از $i به عنوان شمارنده استفاده کنیم و لازم است که این متغیر بتواند تعداد کپی ها را در خود نگهداری پس باید به آن مقدار اولیه اختصاص دهیم و به آن مقدار 0 را اختصاص میدهیم .
+
در خط اول در داخل حلقه تکرار سه بخش مجزا داریم که با semicolon از هم جدا می‌شوند.
<br />
+
 
قسمت دوم مربوط به شرط(condition) است . قبل از انجام هر عملی در حلقه تکرار for این شرط بررسی میگردد اگر true بود حلقه تکرار اجرا میشوند.
+
قسمت اول برای مقدار دهی اولیه(intializing) است ما میخواهیم از $i به عنوان شمارنده استفاده کنیم و لازم است که این متغیر بتواند تعداد کپی‌ها را در خود نگهداری پس باید به آن مقدار اولیه اختصاص دهیم و به آن مقدار 0 را اختصاص می‌دهیم.
<br />
+
 
قسمت آخر افزایش دهنده(increamentor) . این قسمت پس از هربار اجرای حلقه یکبار اجرا میشود.
+
قسمت دوم مربوط به شرط(condition) است. قبل از انجام هر عملی در حلقه تکرار for این شرط بررسی می‌گردد اگر true بود حلقه تکرار اجرا می‌شوند.
<br />
+
 
 +
قسمت آخر افزایش دهنده(increamentor). این قسمت پس از هربار اجرای حلقه یکبار اجرا می‌شود.
 +
 
 
آن باید به صورت زیر اجرا شود :  
 
آن باید به صورت زیر اجرا شود :  
<br />
 
  
ساختن یک متغیر و مقدار دهی اولیه آن 0<br />
+
*ساختن یک متغیر و مقدار دهی اولیه آن
چک کردن شرط حلقه <br />
+
*چک کردن شرط حلقه
اجرای دستورات داخل حلقه (ایجاد یک copy)<br />
+
*اجرای دستورات داخل حلقه (ایجاد یک copy)
سپس مقدار افزاینده به متغیر اضافه میشود و به مرحله دوم میرود.<br /><br />
+
*سپس مقدار افزاینده به متغیر اضافه میشود و به مرحله دوم می‌رود.
شما میتوانید حلقه های تکرار به مراتب پیچیده تری ایجاد کنید . این حلقه تنها یک نمونه آموزشی است .
+
 
<br />
+
شما می‌توانید حلقه‌های تکرار به مراتب پیچیده‌تری ایجاد کنید. این حلقه تنها یک نمونه آموزشی است.
حال میتوانیم از copier استفاده کنیم .ما باید به این منظور از کدهای مانند کدهایی زیر استفاده کنیم :
+
 
 +
حال می‌توانیم از copier استفاده کنیم.ما باید به این منظور از کدهای مانند کدهایی زیر استفاده کنیم :
 +
 
 +
 
 
<source lang="php " >
 
<source lang="php " >
 
$copier = new CopierMultipleCopies();
 
$copier = new CopierMultipleCopies();
سطر ۱۸۸: سطر ۲۶۶:
 
$copier->copy();
 
$copier->copy();
 
</source>
 
</source>
'''این آموزش ادامه دارد'''
+
 
<br />
+
{{در حال تکمیل}}
 +
 
 
منبع : <nowiki> http://docs.joomla.org/Getting_Started_with_Object_Oriented_Programming</nowiki>
 
منبع : <nowiki> http://docs.joomla.org/Getting_Started_with_Object_Oriented_Programming</nowiki>
  
سطر ۱۹۸: سطر ۲۷۷:
 
{{کپی رایت}}
 
{{کپی رایت}}
  
[[رده:مدیریت جوملا]] [[رده:مقالات جوملا]] [[رده:سوالات متداول جوملا]]
+
[[رده:مقالات جوملا]] [[رده:زبان برنامه نویسی تحت وب]]

نسخهٔ کنونی تا ‏۲ فوریهٔ ۲۰۱۲، ساعت ۱۱:۰۱

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 بلامانع است.