آموزش شی گرایی در PHP – مقدمه
در این قسمت از آموزش های پی اچ پی، به آموزش شی گرایی در PHP خواهیم پرداخت. شما با کلیه مفاهیم OOP و نحوه تعریف و استفاده از کلاس، متد و وراثت در PHP آشنا خواهید شد.
در ادامه با روش استفاده از this در برنامه آشنا می گردید. همین طور روش کار access modifier ها و نحوه استفاده از ثابت ها و متدهای آماده را می آموزید.
همچنین با انواع دسترسی به متغیرهای و متدهای یک کلاس و مفاهیم namespace آشنا خواهید شد. ضمن اینکه با روش کار کلاس های abstract و interface و متدهای زنجیره ای آشنا می گردید.
هدف ما در این آموزش، پوشش کلیه مفاهیم شی گرایی و نحوه استفاده از مفاهیم آن در ساختار برنامه می باشد. سعی شده است برای درک کامل از مفاهیم شی گرایی، مثال های کاملی از نحوه استفاده از آن در پی اچ پی، ارائه گردد.
بخش اول: آشنایی با مفاهیم شی گرایی در برنامه نویسی
می توان گفت که برنامه نویسی شی گرا یا همان Object-Oriented Programming یک سبک یا الگو نوشتن کدهاست که به توسعه دهنده ها اجازه می دهد تا بخش های مشابه به هم را در مفهومی به اسم کلاس، گروه بندی نمایند.
در واقع این گروه بندی به برنامه نویسان کمک خواهد کرد که به مفهوم DRY یا همان Don’t Repeat Yourself بیشتر نزدیک گردند، مضاف بر اینکه کدهای آن ها بسیار برای نگهداری و تغییر راحت تر خواهد بود. (به این مفهوم easy-to-maintain گفته می شود).
یکی از مهم ترین مزیت های این سبک از کدنویسی، این می باشد که اگر قرار باشد تکه ای از داده های برنامه شما تغییر یابد، عموما لازم است فقط یک بخش در کدهای شما بروز رسانی گردد.
مهم ترین مزیت برنامه نویسی شی گرا که باعث شده است اکثر developer ها از آن استفاده کنند، شبیه سازی برنامه نویسی با مفاهیم دنیای واقعی است. در واقع شما مفاهیم بسیار پیچیده برنامه نویسی را می توانید با مفاهیم شی گرایی به مفاهیم جاری و قابل فهم در دنیا واقعی تبدیل کنید.
همین طور که می دانید، اطراف ما از اشیا مختلف تشکیل یافته است. هر کدام از آن ها خواصی دارند که آن را از شی مشابه خود، متفاوت می کنید. ضمن اینکه ارتباط بین اشیا با فرستادن پیام بین همدیگر برقرار می گردد.
هر شی می تواند رفتاری از خود بروز دهد که مختص همان شی می باشد. این مفاهیم باعث شد تا همه این ها در مفاهیم برنامه نویسی شی گرا استفاده شود.
در ادامه به طور مفصل در این مورد صحبت خواهد شد. در واقع برنامه نویسی با پیروی از الگوهای OOP ، یک روش برنامه نویسی است که در آن برنامه نویس، تمامی متغیرها و توابعی که بهم مرتبط می باشند را در قالب یک کلاس منفرد، سازمان دهی می کند.
مثل تمام الگوهای برنامه نویسی، این الگو نیز مزایا و معایب خود را دارد که در نوشتار نمی گنجد. به صورت کوتاه می توان گفت ممکن است که در پروژه های ساده و همین طور در سایز کوچک، استفاده از الگوی Procedural که بر مبنای استفاده از توابع می باشد، به صرفه تر باشد.
اما در پروژه هایی با ابعاد بزرگ و پیچیده، مسلما باید از الگوهای شی گرا در برنامه نویسی استفاده کرد چرا که هم باعث کاهش پیچیدگی کدها در آینده خواهد شد و هم نگهداری و عیب یابی آن به مراتب ساده تر از روش های برنامه نویسی رویه ای می باشد.
مهم ترین مفاهیم الگو شی گرایی عبارتند از:
کلاس – Class
شی – Object
خاصیت ها و رفتار کلاس – Property and Method
ارث بری یا وراثت – Inheritance
چند ریختی – Polymorphism
کپسوله سازی – Encapsulation
درک مفهوم کلاس و شی
قبل از اینکه وارد مفاهیم عمیق تر در شی گرایی گردیم، ابتدا درک مفاهیم کلاس و اشیا بسیار حیاتی می باشد. دو مفهوم class و object ، مفاهیمی هستند که خیلی اوقات اشتباه توسط توسعه دهندگان به کار برده می شوند.
همانگونه که در عکس می بینید، یک کلاس می تواند یک طرح کلی و اولیه از یک خانه باشد (یا همان blueprint). در واقع کلاس شکل و اندازه های بخش های مختلف یک خانه را بیان می کند. اما در واقع این طرح کلی درواقع یک خانه واقعی نیست.
در واقع این پلن اولیه، اصلا وجود خارجی ندارد، اما کاملا مشخص می کند که یک خانه چطور و چگونه باید ساخته شود. در این طرح اولیه به صورت کامل شرح داده می شود که یک خانه چه اجزایی دارد و آن ها چگونه باید در داخل خانه جایگذاری گردند.
در واقع یک شی، یک نمونه واقعی از خانه ساخته شده یا خانه ای است که از روی نقشه خانه ساخته شده است. این خانه دقیقا از روی نقشه تهیه شده و اجزا آن کاملا مانند blueprint اولیه می باشد.
در واقع داده هایی که در این شی یا خانه واقعی ذخیره شده، همان چوب و سنگ و سیمان و سیم ها و سایر اجزایی است که یک خانه از آن ها تشکیل شده است. این اجزا بدون قرار گرفتن در کنار هم و اسمبل نشدن، در واقع مفهمومی به نام خانه را به وجود نخواهند آورد.
تعریف کلاس و اشیا
کلاس ها ساختارهای داده ها و عملیات مرتبط به آن ها را گروه بندی می کنند و می توان از اطلاعات یک کلاس برای ساختن اشیا استفاده کرد.
اشیا در واقع نمونه های واقعی از یک کلاس هستند که دارای خواص آن کلاس به همراه داده های واقعی و همین طور رفتار مشابه با کلاس هستند.
حرفه ای ترین و به روزترین مقالات در حوزه وب
بخش دوم: تعریف کلاس در PHP و ساخت اشیا
اولین بخش از مفاهیم شی گرایی در PHP شامل نحوه تعریف کلاس، اشیا و نحوه دسترسی به آن ها می باشد. در این قسمت ابتدا به تعریف کلاس در پی اچ پی اشاره خواهیم کرد. سپس می آموزیم که چگونه یک شی از آن ساخته می شود.
پس از آن به تعریف متد و خاصیت های یک کلاس و سطح دسترسی به آن ها خواهیم پرداخت. در ادامه به تشریح متدهای جادویی و بخش مهم آن یعنی متد construct خواهیم پرداخت.
تعریف کلاس و ساخت شی از آن درPHP
برای تعریف یک کلاس باید از کلمه کلیدی class به صورت روبرو استفاده کنیم. برای ساخت شی از آن کافی است کلمه کلیدی new استفاده کنیم:
class MyClass { // Class properties and methods } $obj = new MyClass;
تعریف متد ها و خاصیت های کلاس در PHP
برای اینکه با ساختار تعریف متد و همین طور خواص در یک کلاس آشنا شوید، از یک مثال استفاده کرده ایم. در ادامه توضیحات مربوط به این مثال آمده است.
در صورتی که کدهای زیر را در یک فایل با پسوند php ذخیره کنید، می توانید به راحتی آن را در localhost خود و با استفاده از WAMP یا XAMP یا MAMP به اجرا در آورید:
//create a class class MsnCar { //define properties in a class public $name; private $wheel_count = 4; private $door_count; protected $company; public static $car_static_property = "This is for parent class"; /** * MsnCar constructor. * @param $name * @param int $wheel_count */ public function __construct($name=null, $wheel_count=null) { $this->name = $name; $this->wheel_count = $wheel_count; } //Sample of setter and getters /** * @return mixed */ public function getCompany() { return $this->company; } /** * @param mixed $company */ public function setCompany($company) { $this->company = $company; } /** * @return int */ public function getWheelCount() { //Sample of property referencing in a class return $this->wheel_count; } /** * @param int $wheel_count */ public function setWheelCount($wheel_count) { $this->wheel_count = $wheel_count; } /** * @return mixed */ public function getDoorCount() { return $this->door_count; } /** * @param mixed $door_count */ public function setDoorCount($door_count) { $this->door_count = $door_count; } //create a method in a class function moving() { echo "Now I'm moving So fast".'<br>'; } function stopping() { echo "Now I'm stopping so well".'<br>'; } //using properties object inside a class method function car_details() { echo $this->name.' has '.$this->wheel_count.' wheels and '.$this->door_count.' doors'; } //Sample of static method to referencing parent class public static function car_reference() { echo self::$car_static_property.'<br>'; //sample of late static binding echo static::$car_static_property.'<br>'; } } //Instantiating of a class $bmw = new MsnCar(); $benz = new MsnCar(); $myPride = new Pride(); //Invoke property of an object echo $bmw->getWheelCount()."<br>"; //change or assign new value to object properties $bmw->setDoorCount(2); $benz->setWheelCount(6); echo $bmw->getDoorCount()."<br>"; echo $benz->getWheelCount()."<br>";
تعریف خصوصیات کلاس در PHP :
Property یا خاصیت برای تعریف متغیر یا اضافه کردن داده به یک کلاس مورد استفاده قرار می گیرد. همان طور که می بینید برای تعریف Property در یک کلاس از همان تعریف متغیر در پی اچ پی استفاده می شود، تنها تفاوت آن این می باشد که هر متغیر دارای یک سطح دسترسی است که جلوتر در مورد آن توضیح داده خواهد شد.
توجه داشته باشید که برای تعریف یک ثابت، می توانید از کلمه کلیدی const استفاده کنید. همان طور که می بینید، کلاسی با نام MsnClass تعریف شده است که دارای Property ها (یا خاصیت هایی) به شکل زیر می باشد:
//define properties in a class public $name; private $wheel_count = 4; private $door_count; protected $company; public static $car_static_property = "This is for parent class"; const site="wpwebmaster.ir";
تعریف متد های کلاس در PHP :
Method ها در واقع توابعی هستند که در یک کلاس تعریف شده و مورد استفاده قرار می گیرند. همان طور که می بینید برای تعریف متد در یک کلاس از همان تعریف تابع درPHP استفاده می شود، تنها تفاوت آن این می باشد که هر متد دارای یک سطح دسترسی است که جلوتر در مورد آن توضیح داده خواهد شد.
همان طور که می بینید، کلاسی با نام MsnClass تعریف شده است که دارای متدهایی به شکل زیر می باشد:
//create a method in a class public function moving() { echo "Now I'm moving So fast".'<br>'; } public function stopping() { echo "Now I'm stopping so well".'<br>'; }
روش استفاده از متغیرها و متدهای یک کلاس در PHP :
برای استفاده از متغیرها و متدهای یک کلاس حتما باید یک نمونه یا شی از آن کلاس ساخته شود تا بتوان متغیر های آن کلاس را مقداردهی کرده و از متدهای آن استفاده کرد. (این مورد در مورد متغییر و متد استاتیک صادق نیست)
نحوه مقدار دهی به متغیرها، همانند مقداردهی به متغیر در php می باشد، با این تفاوت که باید حتما از نام شی و سپس علامت class accessor و سپس نام متغیر استفاده نمود. برای توابع یا متد هم به همین صورت می باشد و اینکه حتما باید از () و در صورت نیاز، تعریف پارامترهای ارسالی به تابع، استفاده کرد.
//Instantiating of a class $bmw = new MsnCar(); $benz = new MsnCar(); $myPride = new Pride(); //Invoke property of an object echo $bmw->getWheelCount()."<br>"; echo $myPride->moving();
متغیر استاتیک و متد استاتیک در یک کلاس :
در صورتی که یک متغیر یا یک کلاس در بین همه اعضای یک کلاس مشترک باشد، آن را از نوع استاتیک تعریف می کنند. برای استفاده از یک متغیر استاتیک لازم نیست که حتما شی ای از کلاس ساخته شود.
متغیر استاتیک و همین طور متدهای استاتیک با استفاده از نام کلاس و استفاده از علامت Scope Resolution یا همان :: فراخوانی می شوند.
نکته مهم در مورد متغیرها و متدهای استاتیک
برای استفاده از متغیرها و متدهای یک کلاس، حتما می باید یک شی از آن ساخته شود اما برای استفاده از متغیر یا متد استاتیک، نیازی به ساخت یک شی نیست. در واقع برای بار اول که کلاس در حافظه ایجاد می گردد یا instantiate می گردد، شما به راحتی می توانید از نام کلاس به همراه علامت scope resolution برای استفاده از آن بهره ببرید.
از آنجایی که ساخت شی در حافظه مستلزم صرف حافظه می باشد، لذا استفاده از متغیرها و متدهای استاتیک، باعث کاهش چشمگیر حافظه مصرفی برنامه شما خواهد شد. عموما متغیرهای استاتیک ساخته شده به عنوان counter یا شمارنده مورد استفاده قرار می گیرند. همچنین متدهای استاتیک، عموما در کلاس های utility یا کمکی که جهت سرویس دهی به کلاس اصلی می باشند، ساخته می شوند.
کلاس های کمکی عموما کارهایی مثل تبدیل واحد، encryption یا رمزنگاری و sanitation را به انجام می رسانند.
//create a class class MsnCar { //define static property in a class public static $car_static_property = "This is a static property in a class"; //Sample of static method in a class public static function moving() { echo 'Hey, All of cars move!<br>'; } } echo MsnCar::car_static_property; MsnCar::moving();
تعریف سطح دسترسی به متدها و متغیرهای کلاس در PHP
شما می توانند برای متغیر ها و متدهای کلاس خود، تعریف کنید که چگونه قابل دسترس باشند. در واقع شما می توانید قابلیت دیده شدن آن ها در خارج و داخل کلاس را تعریف نمایید (Assigning Visibility).
عموما در مفاهیم شی گرایی، خواص یا متغیر های یک کلاس به صورت خصوصی تعریف می شوند تا از دستکاری کردن از آن ها در خارج از کلاس جلوگیری شود. از طرف دیگر در ارث بری، ممکن است بخواهیم به خواص یک کلاس والد یا parent و یا بالعکس، دسترسی داشتیم و امکان تغییر در خارج از آن وجود نداشته باشد.
همچنین اکثر متدها برای دسترسی به رفتار یک شی، به صورت عمومی تعریف می شوند. البته این بسته به نوع طراحی کلاس ممکن است متفاوت باشد. بر مبنای همین موارد، سه نوع دسترسی به متغیر ها و متدهای یک کلاس در پی اچ پی، تعریف شده است.
شما با استفاده از کلمات کلیدی زیر، می توانید نحوه دسترسی به یک کلاس را کنترل نمایید:
سطح دسترسی به صورت public :
در این نوع سطح دسترسی، متد یا متغیری که با public مشخص می شود، قابل دسترس برای همه (چه از داخل کلاس و چه از خارج کلاس) خواهد بود.
سطح دسترسی به صورت private :
در این حالت فقط می توان به متغیر یا متد از داخل کلاس دسترسی داشت. دسترسی از خارج کلاس به متد یا متغیر از نوع private امکان پذیر نیست.
سطح دسترسی به صورت protected :
در حالت protected کلاس و همین طور سایر کلاس هایی که از کلاس جاری ارث برده اند (یا همان کلاس های فرزند) می توانند به متغیر یا متدی با این نوع دسترسی داشته باشند.
چرا باید از Access Modifier یا سطوح دسترسی در شی گرایی در PHP استفاده کنیم؟
در واقع با این کار، کلیه اعمال ویرایشی که از خارج کلاس بخواهد بر روی اعضای داخل کلاس (متدها و خاصیت ها) اعمال گردد را، محدود می کنیم. در واقع فقط متدهای تعریف شده یک کلاس اجازه دسترسی و تغییرات بر روی اعضای یک کلاس را دارند.
در واقع از بیرون یک کلاس نمی توان به آن تزریق کرد و ما با محدود سازی و اعتبارسنجی، جلوی این کار را خواهیم گرفت. ما توسط دادن سطح دسترسی، تمامی داده هایی که خارج از کد کلاس، وارد سیستم می شوند را مورد اعتبارسنجی قرار داده و فیلتر می کنیم. بنابراین احتمال آسیب دیدگی برنامه خود را تقریبا به صفر نزدیک و امنیت داده های سیستم را تضمین می کنیم.
class MsnCar { //define properties in a class with several visibility public $name; private $wheel_count = 4; private $door_count; protected $company; public static $car_static_property = "This is for parent class"; //Define access modifier for functions public static function moving() { echo "Now I'm moving So fast".'<br>'; } }
همانگونه که بیان شد، برای جلوگیری از دسترسی مستقیم به داده های یک کلاس یا چک کردن آن ها مثلا پیش از ذخیره در دیتابیس، عموما متغیرهای یک کلاس را از نوع private تعریف می کنند.
به همین دلیل، از آنجایی که نمی توان به صورت مستقیم به این متغیر ها دسترسی داشت، باید تابع هایی به عنوان Getter و Setter تعریف نمود تا بتوان متغیرها را از داخل کلاس فراخوانی نمود و یا مقدار آن ها را تغییر داد.
برای دسترسی در داخل کلاس به متغیر ها و متدهای شی ساخته از آن کلاس از کلمه کلیدی با نام this و همین طور علامت <- استفاده می شود. مفاهیم گفته شده به صورت خلاصه در زیر تشریح شده است:
استفاده از کلمه کلیدی this برای دسترسی به متدها به متغیرهای یک شی در داخل کلاس:
برای دسترسی به متغیرهای داخل یک کلاس توسط متدها یا سایر متغیرهای یک شی، از کلمه کلیدی this استفاده می شود.
استفاده از کلمه کلیدی self برای دسترسی به متدها به متغیرهای استاتیک در داخل کلاس:
از آن جایی که متغیر استاتیک متعلق به یک object می باشد، لذا در متدهای استاتیک یا سایر متدها، برای دسترسی به آن نمی توان از کلمه کلیدی this استفاده کرد.
در این موارد برای دسترسی به متدها یا خواص استاتیک در متدهای معمولی، از کلمه کلیدی self به همراه علامت Scope Resolution استفاده می کنیم.
استفاده از تابع getter برای دسترسی به متغیر از نوع private در کلاس :
برای دسترسی به محتوا یا داده داخل یک متغیر از نوع private از توابع getter استفاده می شود. این تابع ها دارای سطح دسترسی public بوده و با ساخته شدن یک شی، از داخل کلاس به محتوای private دسترسی پیدا می کنند. برای خوانایی بهتر کدهای برنامه، این توابع عموما با نام get آغاز می شوند.
استفاده از تابع setter برای تغییر مقدار متغیر از نوع private در کلاس :
برای تغییر دادن محتوا یا داده داخل یک متغیر از نوع private از توابع setter استفاده می شود. این تابع ها دارای سطح دسترسی public بوده و با ساخته شدن یک شی، از داخل کلاس به محتوای داده private دسترسی پیدا می کنند. برای خوانایی بهتر کدهای برنامه، این توابع عموما با نام set آغاز می شوند.
//Sample of setter and getters /** * @return mixed */ public function getCompany() { return $this->company; } /** * @param mixed $company */ public function setCompany($company) { $this->company = $company; } /** * @return int */ public function getWheelCount() { //Sample of property referencing in a class return $this->wheel_count; } /** * @param int $wheel_count */ public function setWheelCount($wheel_count) { $this->wheel_count = $wheel_count; } /** * @return mixed */ public function getDoorCount() { return $this->door_count; } /** * @param mixed $door_count */ public function setDoorCount($door_count) { $this->door_count = $door_count; } //using properties object inside a class method function car_details() { echo $this->name.' has '.$this->wheel_count.' wheels and '.$this->door_count.' doors'; }
متدهای زنجیره ای و روش استفاده از آن در شی گرایی در PHP
گاهی اوقات ممکن است نیاز داشته باشیم که کلاس را خلاصه تر پیاده سازی کرده و همین طور سرعت مقداردهی در آن را بالاتر ببریم.
در اینگونه موارد، برای مقداردهی یک property، از چندین متد در داخل کلاس استفاده کرده و آن ها را به صورت زنجیره ای فراخوانی می کنیم.
در همه توابع یک return داریم در انتها و در متد آخر، مقدار برگشتی را echo می کنیم.
class Person{ protected $person_info; public function name($value){ $this->person_info .= "Name: $value, "; return $this; } public function family($value){ $this->person_info .= "Family: $value, "; return $this; } public function birthday($value){ echo $this->person_info .= "Born on: $value"; } } $gholam = new Person(); $gholam->name("gholam")->family("Palang")->birthday("1-1-1"); /* * The result is: * Name: gholam, Family: Palang, Born on: 1-1-1 * */
متدهای زنجیره ای با استفاده از ترکیب متدهای استاتیک در PHP
شما می توانید برای پیاده سازی متدهای زنجیره ای، از ترکیب متدهای استاتیک استفاده نمایید. فقط داخل بدنه باید به جای this از کلمه کلیدی self استفاده کنیم.
توجه کنید که در مثال قبل، برای مقدار بازگشتی از کلمه this استفاده می کردیم اما در اینجا از new static استفاده می کنیم.
<?php class Person{ static protected $person_info; static public function name($value){ self::$person_info .= "Name: $value, "; return new static; } public function family($value){ self::$person_info .= "Family: $value, "; return new static; } public function birthday($value){ echo self::$person_info .= "Born on: $value"; } } $gholaidoon = new Person(); $gholaidoon->name("gholaidoon")->family("Palang")->birthday("1-1-1"); /* * The result is: * Name: gholaidoon, Family: Palang, Born on: 1-1-1 * */
متدهای جادوی و روش استفاده از آن در شی گرایی در PHP
جهت ساده سازی کار برنامه نویسان برای ساختن و استفاده کردن از object های ساخته شده از class ها، چندین متد با نام های متدهای جادویی در زبان PHP قرار داده شده است.
این متدهای با علامت __ (دو underline به صورت پشت سرهم) شروع می شوند. معمولا قبل از متدهای جادویی از access modifier های مثل public یا private یا protected استفاده نمی شود.
متدهای جادویی در که در شی گرایی در php استفاده می شوند، به شرح زیر می باشند:
__construct __destruct __call __callStatic __get __set __isset
__unset __sleep __wakeup __toString __invoke __set_state __clone
نحوه استفاده از متد جادویی construct در PHP:
زمانی که تصمیم داشته باشیم برای ساخت یک شی از یک کلاس، عملیات خاص یا مقداردهی خاصی را انجام دهیم، از این متد استفاده می شود. به این متد اصطلاح سازنده کلاس یا constructor نیز گفته می شود.
عموما برنامه نویسان برای مقدار دهی اولیه به متغیرهای شی ساخته شده (برای جلوگیری از null بودن مقادیر آن ها) از این متد استفاده می کنند. توجه داشته باشید که متد همین که یک object جدید از یک کلاس ساخته می شود، به صورت اتوماتیک فراخوانی می شود.
در داخل متد construct نمی توان از return نیز استفاده کنید. در واقع هرگاه که بخواهیم دقیقا پس از ساخته شدن شی، کاری را روی آن انجام دهیم، از متد جادویی construct استفاده می کنیم.
//create a class class MsnCar { //define properties in a class public $name; private $wheel_count = 4; private $door_count; protected $company; public static $car_static_property = "This is for parent class"; /** * MsnCar constructor. * @param $name * @param int $wheel_count */ public function __construct($name="pride", $wheel_count=4) { $this->name = $name; $this->wheel_count = $wheel_count; } } $benz = new MsnCar("benz1",6);
نحوه استفاده از متد جادویی destruct در PHP:
این مفهوم دقیقا عکس مفهوم construct عمل می کند، در واقع متد destruct دقیقا قبل از اینکه شی ساخته شده از یک کلاس، از بین برود، فراخوانی می شود. این متد با عنوان Destructor یا از بین برنده برای object ساخته شده از یک کلاس، شناخته می شود.
این متد دقیقا پیش از زمانی که شی در حافظه destroy می شود (یا از بین می رود) به اجرا در می آید. به عنوان مثال زمانی که شما متد unset را بر روی یک شی فراخوانی می کند، این متد پیش از unset کردن شی مورد نظر، اجرا می گردد.
در نظر داشته باشید متد جادویی destruct نمی تواند پارامتر ورودی دریافت نماید.
class MsnCar { function __construct() { echo 'It is called after creating an object from MsnCar class'; } function __destruct() { echo 'It is called before destroying an object from MsnCar class'; } }
نحوه استفاده از متد جادویی tostring در PHP:
در صورتی که بر روی شی ساخته شده از یک کلاس، تابع echo را فراخوانی کنیم، این متد در کلاس به اجرا در می آید.
نحوه استفاده از متد جادویی set در PHP:
این متد بر روی یک object زمانی فراخوانی می شود، که بخواهیم مقداری را به یک property بر روی شی نسبت دهیم که این خاصیت یا در کلاس مربوط به آن شی وجود ندارد یا دسترسی لازم برای تغییر آن برای ما وجود ندارد.
در واقع از این متد می توان برای ساختن متغیر داینامیک برای یک کلاس بهره برد. متد جادویی set دو آرگومان ورودی می پذیرد که اولی نام خاصیت مورد نظر و دومی مقداری می باشد که قرار است به آن اختصاص دهیم.
نحوه استفاده از متد جادویی get در PHP:
برای دسترسی به متغیرهایی که با روش بالا و استفاده از متد جادویی set تعریف شده اند، می توانید از متد جادویی get استفاده نمایید. در واقع این متد زمانی فراخوانی می شود که ما بخواهیم به یک property دسترسی باشیم که یا در کلاس ما وجود ندارد و یا سطح دسترسی به آن وجود ندارد.
به عنوان مثال ما می توانیم از بیرون کلاس با متد جادویی get خاصیت هایی از کلاس که به صورت private تعریف شده اند را نمایش بدهیم.
نحوه استفاده از متد جادویی isset در PHP:
برای چک کردن اینکه property های غیر قابل دسترس در یک کلاس یا همان private، یا property هایی که به صورت داینامیک در کلاس تعریف شده اند، مقداردهی اولیه شده اند، از متد جادویی isset استفاده می کنیم.
نحوه استفاده از متد جادویی unset در PHP:
برای unset کردن property هایی که در قسمت های قبل صحبت کردیم از متد جادویی unset در php استفاده می کنیم.
نحوه استفاده از متد جادویی clone در PHP:
زمانی که بخواهیم از یک شی با استفاده از روش copy by value یک کپی تهیه کنیم، از متد جادویی clone استفاده می کنیم.
class MsnCar { //define properties in a class public $name; protected $company; private $wheel_count = 4; private $door_count; /** Location for overloaded data. */ private $data = array(); public function __construct($name, $door_count, $company) { $this->name = $name; $this->door_count = $door_count; $this->company = $company; } public function __toString() { return 'The name of car is ' . $this->name . ' and from ' . $this->company . ' with ' . $this->door_count . ' doors!!!<br>'; } public function __get($name) { echo "Getting '$name':"; if (array_key_exists($name, $this->data)) { return $this->data[$name].'<br>'; } $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } public function __set($name, $value) { echo "Setting '$name' to '$value'<br>"; $this->data[$name] = $value; } /** As of PHP 5.1.0 */ public function __isset($name) { echo " Is '$name' set? "; return isset($this->data[$name]).'<br>'; } /** As of PHP 5.1.0 */ public function __unset($name) { echo "Unsetting '$name'<br>"; unset($this->data[$name]); } } $pride = new MsnCar('pride', 6, 'SAIPA PALANG'); echo $pride; $pride->color = 'Ghermez Jigari'; echo $pride->color; var_dump(isset($pride->color)); unset($pride->color); echo $pride->color; /* Return of your code is in the following: The name of car is pride and from SAIPA PALANG with 6 doors!!! Setting 'color' to 'Ghermez Jigari' Getting 'color':Ghermez Jigari Is 'color' set? bool(true) Unsetting 'color' Getting 'color': Notice: Undefined property via __get(): color in C:\wamp64\www\PHP\00\oop\MsnCar.php on line 75 in C:\wamp64\www\PHP\00\oop\MsnCar.php on line 44 */
نحوه استفاده از متد جادویی call در PHP:
زمانی که بخواهیم متدهایی به صورت داینامیک برای یک شی بسازیم که در کلاس سازنده آن وجود ندارد، از متد جادویی call استفاده می کنیم.
متد جادویی call دو پارامتر ورودی دریافت می کند، اولی نام تابع داینامیکی است که می خواهیم آن را ایجاد کنیم. دومی آرایه ای از پارامترهایی است که می خواهیم به آن پاس بدهیم.
یک مثال بسیار کاربردی در این زمینه: فرض کنید شما یک کلاس برای کار با database خود دارید. شما می خواهید در داخل کلاس متدهایی داشته باشید که بتوانید با استفاده از آن، یک فیلد با یک مقدار مشخص در دیتابیس را جستجو کنید.
یک روش این می باشد، که برای هر فیلد داخل دیتابیس، یک متد با نام مثلا findByID و الی آخر بنویسید. مسلما اگر تعداد فیلدهای جدول شما بسیار زیاد باشد، این کار عملا روش کارایی محسوب نمی گردد.
بهترین راه برای انجام این کار استفاده از متد جادویی call می باشد که می توانید با آن متدهای داینامیک برای جستجو در داخل جدول خود بر اساس نام فیلد درست کنید. مثال زیر این امر را نمایش می دهد.
class Database { function __call($method, $args) { $field = strtolower(substr($method, 6, strlen($method) - 6)); $sql = "SELECT * FROM $this->table WHERE $field = $args[0] "; return $this->db->query($sql); } } $db = new Database(); $db->findByID(28); $db->findByName('gholam');
نحوه استفاده از متد جادویی callstatic در PHP:
این متد زمانی اجرا می شود که می خواهیم به متد استاتیکی از کلاس دسترسی داشته باشیم که قابلیت دسترسی به آن وجود دارد (یا تعریف نشده یا سطح دسترسی به آن private تعریف شده است)
class MethodTest { public function __call($name, $arguments) { // Note: value of $name is case sensitive. echo "Calling object method '$name' " . implode(', ', $arguments). "<br>"; } public static function __callStatic($name, $arguments) { // Note: value of $name is case sensitive. echo "Calling static method '$name' " . implode(', ', $arguments). "<br>"; } } $obj = new MethodTest; $obj->runTest('in object context'); MethodTest::runTest('in static context'); /* The reuslt is something like this in the following: Calling object method 'runTest' in object context Calling static method 'runTest' in static context */
نحوه استفاده از متد جادویی sleep در PHP:
زمانی که بخواهیم روی یک شی تابع serialize را فراخوانی کنیم، متد جادویی sleep اجرا خواهد شد.
هنگامی که شما یک کلاس را serialize می کنید، همه متغیر ها و اعضای آن کلاس به صورت serialize شده، ذخیره می گردند. اما گاهی نیاز نیست که همه متغیرها را نگهداری کنیم.
در این گونه موارد از متد جادویی sleep استفاده خواهیم کرد. در واقع داخل متد جادویی sleep می توانیم مشخص کنیم که چه متغیر هایی از کلاس اجازه serialize شدن را دارند.
نحوه استفاده از متد جادویی wakeup در PHP:
متد جادویی wakeup در زمان فراخوانی تابع unserialize اجرا می شود.
class Connection { protected $link; private $dsn, $username, $password; public function __construct($dsn, $username, $password) { $this->dsn = $dsn; $this->username = $username; $this->password = $password; $this->connect(); } private function connect() { $this->link = new PDO($this->dsn, $this->username, $this->password); } public function __sleep() { return array('dsn', 'username', 'password'); } public function __wakeup() { $this->connect(); } }
بخش سوم: ارث بری در PHP
در این بخش می خواهیم به مفاهیم وراثت در پی اچ پی بپردازیم. در ابتدا نیاز داریم که با مفهوم ارث بری و اینکه چرا در شی گرایی، به ارث بری نیاز داریم بپردازیم.
می توان گفت از مهم ترین مزیت هایی که باعث می شود به سمت برنامه نویسی شی گرا سوق پیدا کنیم، کاهش نوشتن خط های اضافی کد و کم شدن کدهای تکراری در برنامه ما می باشد. در واقع ما با استفاده از وراثت به مقدار بسیار زیادی از code duplication جلوگیری خواهیم کرد.
در مفهوم Inheritance از یک کلاس والد یا همان parent class استفاده می شود. این کلاس دارای تعدادی خواص و رفتارهای مربوط به خود می باشد. حال کلاسی به نام کلاس فرزند یا child class تعریف می گردد که می تواند تمامی خواص و رفتارهای کلاس والد خود را به ارث ببرد.
علاوه بر این، کلاس فرزند می تواند property ها و method های جدیدی برای خودش داشته باشد که در کلاس والد وجود ندارد. همچنین کلاس فرزند می تواند رفتار و خواص متد والد خود را مورد بازنویسی قرار دهد (در ادامه به آن به صورت کامل اشاره خواهد شد).
در واقع مفهوم وراثت این امکان را به ما می دهد که کدهای خود را تنها یک بار در کلاس پدر نوشته و به کرات آن را در کلاس های فرزندی که از کلاس پدر ارث برده اند، استفاده نماییم.
در مورد وراثت و نحوه ارث بری در PHP نکاتی وجود دارد که در زیر به آن ها اشاره شده است:
نحوه ارث بری یک کلاس از کلاس دیگر در PHP:
برای اینکه بتوانید از یک کلاس ارث ببرید، کافی است از کلمه extends به صورت زیر استفاده نمایید. در نظر داشته باشید، با ارث بردن از کلاس والد، کلیه خاصیت ها و متدهای کلاس parent برای کلاس child هم به همان شکل تعریف می گردند.
class MsnCar { //define properties in a class public $name; protected $company; private $wheel_count = 4; private $door_count; public function __construct($name, $door_count, $company) { $this->name = $name; $this->door_count = $door_count; $this->company = $company; } public function moving() { echo "Now I'm moving So fast" . '<br>'; } public function stopping() { echo "Now I'm stopping so well" . '<br>'; } public function __toString() { return 'The name of car is ' . $this->name . ' and from ' . $this->company . ' with ' . $this->door_count . ' doors!!!<br>'; } } //Inheritance in PHP class PrideGhahreman extends MsnCar { public $wings_number; public function __construct($name, $door_count, $company) { parent::__construct($name, $door_count, $company); // Call the parent class's constructor echo "A new constructor in " . __CLASS__ . ".<br />"; } public function parvaz() { echo "You can fly with " . __CLASS__ . ".<br />"; } public function __toString() { $temp = parent::__toString(); return $temp.' This Pride has '.$this->wings_number.' wings'; } } // Create a new object $newobj = new PrideGhahreman('pride 6 dar', 6, 'Saipa Ghashang'); // Define and use new method in child class echo $newobj->parvaz(); // Use a method from the parent class $newobj->moving(); // Use a method from the parent classg $newobj->stopping(); // Define and use new property in child class $newobj->wings_number = 2; // Use a method from the parent class and ovverriding parent method in child method echo $newobj; /* The result is: A new constructor in PrideGhahreman. You can fly with PrideGhahreman. Now I'm moving So fast Now I'm stopping so well The name of car is pride 6 dar and from Saipa Ghashang with 6 doors!!! This Pride has 2 wings */
سطوح دسترسی در استفاده از وراثت در PHP
همانند آنچه در قبل تر در مورد سطح دسترسی ها در PHP بیان شد، کلاس فرزند می تواند تنها به متد ها و property هایی با سطح دسترسی public و protected در کلاس پدر خود دسترسی داشته باشد. کلاس child دسترسی به متدها یا خاصیت های private در کلاس parent را نخواهد داشت.
در نظر داشته در صورتی که متد یا خاصیتی به صورت protected تعریف گردد، امکان دسترسی به آن هم در داخل کلاس والد و هم در کلاس های ارث برده شده از آن، فراهم می باشد.
تعریف property ها و method های اختصاصی در کلاس child
یک کلاس child یا فرزند، علاوه بر اینکه به متدها و خواص کلاس parent خود دسترسی دارد، می تواند دارای متدها و همین طور خاصیت های مربوط به خود باشد. در مثال بالا برای کلاس فرزند، این امر نمایش داده شده است.
مفهوم overriding در PHP
در صورتی که برای متد (یا خواص) موجود در کلاس والد، پیاده سازی جدیدی در کلاس فرزند آن کلاس داشته باشیم، در این صورت می گوییم آن متد یا خاصیت override شده است. در صورتی که متد یا خاصیتی override شده باشد، برای دسترسی به متدهای والد، باید از کلمه کلیدی parent استفاده کنید.
همانگونه که در مثال بالا می بینید، متد construct در کلاس child دوباره نوشته شده و متد construct کلاس parent در داخل آن با کلمه کلیدی parent و استفاده از علامت scope resolution یا :: فراخوانی شده است.
مفهوم overloading: تفاوت overloading با overriding چیست؟
در بسیاری از مواقع این دو مفهوم باهم اشتباه گرفته شده و اسامی آن ها به جای همدیگر به کار برده می شود. در مفهوم overriding که در بالا در مورد آن توضیح داده شد، دو متد دقیقا با یک نام و یک تعداد آرگومان ورودی اما با پیاده سازی متفاوت، در کلاس پدر و در کلاس فرزند موجود می باشند.
اما در overloading، چند متد در یک کلاس با یک نام اما با تعداد آرگومان های ورودی متفاوت، تعریف و پیاده سازی می شوند (این امر بسیار در مورد constructor ها استفاده می شود)
نحوه استفاده از کلمه کلیدی Final برای متد ها در PHP
در صورتی که بخواهید از override شدن یک متد در کلاس فرزند، جلوگیری به عمل آورید، کافی است در ابتدای تعریف متد در کلاس والد، از کلمه کلیدی Final استفاده کنید.
نحوه استفاده از کلمه کلیدی Final برای کلاس در PHP
در صورتی که بخواهید اجازه ارث بری از یک کلاس را بگیرید و نگذارید تا آن کلاس extend گردد، از کلمه کلیدی final در پیش از کلمه class در تعریف کلاس، استفاده می کنید.
شما نمی تواند از خاصیت inheritance بر روی کلاس های final استفاده کنید و نمی توانید از آن ها ارث بری کنید.
مفهوم late static binding در PHP
مفهوم late static binding از مفاهیم بسیار مهم و کاربردی در php می باشد. در پیش تر گفته شد که برای دسترسی به یک متد یا خاصیت از نوع استاتیک در متدهای یا خاصیت معمولی، می باید به جای استفاده از کلمه کلیدی this از کلمه کلیدی self استفاده کنیم.
حال گاهی اوقات ممکن است در کلاس parent بخواهیم از متد یا property ای که به صورت static در کلاس فرزند تعریف شده، استفاده نماییم. به این کار اصطلاحا late static binding گفته می شود.
برای این کار، یعنی استفاده از متد یا خاصیت static کلاس فرزند در کلاس پدر، ار کلمه کلیدی static به جای self استفاده می کنیم. در مقاله ای جداگانه و به صورت کاملا کاربردی، این مورد با مثال به شما نمایش داده خواهد شد (در هنگام ساخت یک کلاس برای دسترسی به دیتابیس و کوئری زدن بر روی آن)
آشنایی با مفهوم auto loading در PHP
مفهوم autoloading یکی از موارد بسیار مهم و کاربردی در PHP می باشد. همواره برای اینکه بتوانیم از یک فایل یا یک کلاس PHP در فایل ها یا کلاس های دیگر استفاده نماییم، می باید محل آن فایل را با دستور include یا require به بالای فایل خود اضافه کنیم.
این امر وقتی برنامه کوچک است و تعداد بخش ها و فایل های آن زیاد نیست، مهم نمی باشد. اما هنگامی که برنامه کمی بزرگ می شود و تعداد بخش های آن افزایش می یابد، این امر بسیار مشکل شده و هر بار می باید تعداد زیادی فایل را قبل از استفاده، include نماییم.
زمانی که تعداد فایل ها افزایش می یابد، مدیریت این کار فوق العاده سخت و پیچیده خواهد شد. در واقع ما باید تمام فایل ها لود کنیم در حالی که فقط به بخشی از آن ها نیاز داریم. در ابتدا برای مدیریت این کار از متد جادویی autoload برای کلاس ها استفاده می شد.
در PHP7 و در SPL یا همان Standard PHP Library تابعی با نام spl_autoload_register معرفی شد. در واقع PHP در صورتی که فایل یا کلاسی را در برنامه ببیند که در ابتدای برنامه تعریف نشده، آن را به این تابع ارجاع می دهد تا این تابع به صورت خودکار، فایل یا کلاس مورد نظر را پیدا کرده و به برنامه اضافه کند.
به این عمل اصطلاحا autoloading گفته می شود. مزیت استفاده از این روش این می باشد که هم استفاده از فضای حافظه کمتر خواهد شد و هم باعث افزایش سرعت پردازش برنامه می گردد.
برای انجام auto loading و استفاده از تابع spl_autoload_register ، شما می باید یک ساختار مشخص برای فایل ها یا کلاس های خود مشخص کنید، تا هنگام ارجاع شدن یک فایل یا کلاس ناشناخته، کلاس autoloading شما بتواند ساختار آن را درست کرده و به برنامه شما اضافه کند.
به عنوان مثال، شما در کلیه کلاس های خود را در یک دایرکتوری می گذارید. همچنین اول اسم کلیه کلاس ها را با -class نام گذاری می کنید.
حال فقط لازم است کلاس autoloader را خود را در هدر صفحات یا تابعی به نام init.php اضافه کنید. پس از آن دیگر نیاز به اضافه کردن فایل ها و کلاس های خود برای شناخته به برنامه ندارید و کلاس autoloader شما به راحتی به صورت خودکار این کار را برای شما انجام خواهد داد.
کد زیر، یک نمونه از کلاس autoloader می باشد. البته در نظر بگیرید که پس از تعریف این کلاس، کلیه کلاس های شما باید با نام -class آغاز گردد تا کلاس autoloader شما بتواند آن ها را به صورت اتوماتیک به برنامه در حال اجرای شما اضافه نماید.
البته روش های دیگری مثل استفاده از composer با استفاده از PSR-0 و PSR-4 وجود دارد که در این مقاله نمی گنجد. حتما در بخش بعدی این مقاله یک مثال عملی و واقعی از این مورد، ارائه خواهد شد.
/***** Autoloder class *****/ class Autoloader { public function __construct() { spl_autoload_register(array($this, 'autoload')); } public function autoload($class_name) { $file = $this->convert_class_to_file($class_name); if (is_file($file) && file_exists($file) && is_readable($file) && !class_exists($class_name)) { //var_dump($file); include $file; }else { die("This file name: {$file} was not found...!"); } } public function convert_class_to_file($class_name) { $class = strtolower($class_name); $class = 'class-'.$class; $filename = "includes/{$class}.php"; return $filename; } } new Autoloader();
بخش چهارم: مفهوم Abstract شی گرایی در PHP
در مفاهیم شی گرایی، زمانی که بخواهیم سایر توسعه دهندگان را الزام کنیم که در هنگام ارث بری از کلاسی، حتما متد خاصی در آن را پیاده سازی کنند، از کلاس ها و متدهای abstract استفاده می کنیم.
در واقع در یک کلاس abstract یا انتزاعی می خواهیم که برنامه نویس حتما متدی که در کلاس والد با نام abstract مشخص شده است را، پیاده سازی نماید.
اگر یک متد abstract در یک کلاس موجود باشد، حتما آن کلاس باید به صورت abstract تعریف گردد. کلاس abstract قابل نمونه گیری یا instantiation نبوده اما قابل ارث بری می باشند.
متدهای انتزاعی در داخل کلاس abstract، دارای فقط اسم و آرگون های ورودی هستند و بدنه آن ها در کلاس abstract یا والد خالی است. در واقع کلاس انتزاعی والد، فقط دارای Method’s Signature می باشد.
بنابراین بدنه متدهای انتزاعی و عملیاتی که قرار است در آن ها انجام شود، در کلاس فرزند که از آن ارث برده است، می باید تعریف گردد. در واقع implementation متد در این بخش باید انجام پذیرد.
در نظر داشته باشید که Visibility یا همان سطح دسترسی متد فرزند، باید مساوی یا بیشتر از سطح دستری متد abstract باشد. یعنی اگر visibility متد انتزاعی در کلاس parent برابر protected باشد، در کلاسی که از آن مشتق شده است، سطح دسترسی نمی تواند private بوده و باید protected یا public باشید.
کلاس های abstract می توانند دارای property ها یا متد هایی باشند که پیاده سازی شده باشند. یعنی یک کلاس انتزاعی می تواند شامل خاصیت ها و همین طور متدهای غیر انتزاعی نیز باشد.
نحوه پیاده سازی کلاس abstract و متد abstract در PHP:
برای اینکه یک کلاس انتزاعی تعریف کنید، کافی است یک یا چند متد abstract در یک کلاس که با کلیدی واژه abstract آغاز شده است را، به صورت زیر تعریف نمایید.
تعریف property و method های غیر انتزاعی در PHP:
همانند یک کلاس معمولی، شما می توانید در داخل یک کلاس abstract ، خواص و متدهای غیر abstract تعریف نمایید.
abstract class AbstractMsnCar { /*Abstract classes can have property*/ protected $tankCapacity; /*Abstract classes can have non abstract method*/ public function setTankCapacity($tankCapacity) { $this->tankCapacity = $tankCapacity; } // Abstract method abstract public function distanceOnFullTank(); }
نحوه ارث بری یک کلاس از کلاس abstract در PHP:
ارث بری از یک کلاس انتزاعی، همانند ارث بری در سایر بخش هاست. فقط حتما باید متدهایی که در کلاس parent تعریف شده اند، در کلاس child بازنویسی شده یا implement گردند.
متد abstract در کلاس والد، هیچ بدنه ای ندارد و در کلاس فرزند، این متد باید override گردد.
class VanetPride extends AbstractMsnCar { public function distanceOnFullTank() { // TODO: Implement distanceOnFullTank() method. $kilometers = $this->tankCapacity*100; return $kilometers; } }
بخش پنجم: مفهوم Interface شی گرایی در PHP
یکی دیگر از مفاهیم شی گرایی، مفهوم interface می باشد. از مفهوم interface در OOP برای موارد متعدد از جمله پیاده سازی چند ریختی استفاده می شود.
مفهوم interface بسیار شبیه کلاس انتزاعی بوده و به نوعی یک کلاس abstract محسوب می شود. تفاوت آن ها این می باشد که در داخل interface ها هیچ متدی که دارای بدنه باشد، نمی تواند تعریف شود.
هر کلاسی که از یک interface مشتق شده باشد باید کلیه متدهای کلاس پدر خود را بازنویسی نماید. درون interface نمی توان property تعریف کرد. ضمن اینکه کلیه متدهای داخل یک interface باید دارای سطح دسترسی public باشند.
با توجه به مفهوم interface در شی گرایی، یک interface نمی تواند دارای متد غیر انتزاعی باشد. در واقع کلیه متدهای داخل یک interface به صورت abstract هستند.
اساسی ترین کاربرد interface در زبان PHP
مهم ترین کاربرد interface در زبان PHP پیاده سازی مفهوم Multi Inheritance یا وراثت چند گانه می باشد. یک کلاس تنها می تواند از یک کلاس دیگر ارث بری کند اما می تواند چندین interface را پیاده سازی یا implement نماید.
نحوه پیاده سازی یک interface در PHP:
برای تعریف interface به جای استفاده از کلمه کلیدی class باید از کلمه کلیدی interface استفاده نمایید. در نظر داشته باشید که interface فقط می تواند شامل متد های abstract و ثابت ها یا همان constants باشد.
هیچ متغیر یا property ای را نمی توان در interface تعریف نمود.
نحوه ارث بری از interface در PHP:
برای اینکه یک کلاس فرزند بتواند از یک interface مشتق گردد، می باید در تعریف خود به جای کلمه کلیدی extends از کلمه کلیدی implements استفاده کند.
در نظر داشته باشید که کلیه متدهایی که در interface تعریف شده اند، باید به صورت کامل در کلاس child پیاده سازی یا implement گردند.
interface Pride { public function setModel($name); public function getModel(); } class PrideGhoorbagheyi implements Pride { private $model; public function getModel() { return $this->model; } public function setModel($name) { $this->model = $name; } }
ارث بری interface ها یا extendable interface در PHP:
هر interface می تواند از یک یا چندین interface دیگر مشتق گردد. اما یک کلاس تنها می تواند از یک کلاس دیگر مشتق گردد.
interface a { public function foo(); } interface b extends a { public function baz(Baz $baz); } // This will work class c implements b { public function foo() { } public function baz(Baz $baz) { } } // This will not work and result in a fatal error class d implements b { public function foo() { } public function baz(Foo $foo) { } }
نحوه پیاده سازی ارث بری چندگانه یا Multiple interface inheritance در PHP:
یکی از قابلیت های بسیار کاربردی استفاده از interface پیاده سازی ارث بری چندگانه یا همان Multiple Inheritance می باشد. در شما می توانید چندین interface را در یک کلاس implement یا پیاده سازی کنید.
در واقع یک کلاس می تواند بیش از یک اینترفیس را implement کند. در مثال بالا فرض کنید بخواهیم کلاس PrideGhoorbagheyi از دو کلاس Pride و Vehicle ارث برده و آن ها را پیاده سازی نماید.
پیاده سازی آن به صورت زیر خواهد بود:
interface Vehicle { public function setHasWheels($bool); public function getHasWheels(); } class PrideGhoorbagheyi implements Pride, Vehicle { private $model; private $hasWheels; public function getModel() { return $this->model; } public function setModel($name) { $this->model = $name; } public function getHasWheels() { return ($this->hasWheels) ? "has wheels" : "no wheels"; } public function setHasWheels($bool) { $this->hasWheels = $bool; } }
بخش ششم: مفهوم Polymorphism شی گرایی و پیاده سازی آن در PHP
یکی از موارد بسیار کاربردی در شی گرایی، پولی مورفیسم یا Polymorphism می باشد. در فارسی از آن به عنوان چند ریختی یاد می شود.
در معنی، پولی مورفیسم وقتی اتفاق می افتد که کلیه کلاس های ارث برده از یک کلاس دارای یک متد از کلاس والد هستند. این متد بین همه آن ها مشترک است اما رفتار این متد در هرکدام از کلاس ها متفاوت می باشد. متد کلاس فرزند بسته به نوع کلاس، پیاده سازی متفاوتی دارد.
از معروف ترین مثال ها در زمینه چند ریختی در شی گرایی، عکسی است که در بالا نمایش داده شده است. همان گونه که می بینید، کلاس Shape یا همان شکل، دارای متد draw یا کشیدن می باشد.
کلیه اشکال مثل خط، دایره، مثلث و مستطیل، از کلاس شکل و متد کشیدن آن ارث می برند. اما نحوه کشیدن در هر شکل، بسته به نوع آن فرق دارد. به این حالت چند ریختی گفته می شود.
مثال زیر نیز به خوبی این مورد را نمایش می دهد. در این مثال متد محاسبه مساحت یک شکل در اشکال مختلف باهم فرق می کند اما همه آن ها یک نام داشته و از یک پدر یعنی کلاس shape ارث برده اند.
interface Shape { public function calcArea(); } class Circle implements Shape { private $radius; public function __construct($radius) { $this->radius = $radius; } // calcArea calculates the area of circles public function calcArea() { return $this->radius * $this->radius * pi(); } } class Rectangle implements Shape { private $width; private $height; public function __construct($width, $height) { $this->width = $width; $this->height = $height; } // calcArea calculates the area of rectangles public function calcArea() { return $this->width * $this->height; } } $circ = new Circle(3); $rect = new Rectangle(3, 4); echo $circ->calcArea(); echo $rect->calcArea(); /* * The result is: ۲۸.۲۷۴۳۳۳۸۸۲۳۰۸ ۱۲ * */
بخش هفتم: مفهوم Encapsulation شی گرایی و استفاده از namespace در PHP
یکی دیگر از مفاهیم شی گرایی در PHP، مفهوم Encapsulation و نحوه پیاده سازی آن می باشد. در واقع namespace ها راهی برای کپسوله سازی داده ها و آیتم ها در PHP می باشد.
در دنیای پی اچ پی namespace ها برای حل دو مشکل اصلی طراحی شده اند که عموما کتابخانه ها و برنامه های توسعه دهندگان، با آن ها هنگام برنامه نویسی مواجه می شدند.
در واقع شما، وقتی بخش هایی از کد که برای استفاده مجدد می نویسید، مانند کلاس ها و تابع ها را، می سازید، عموما با دو مشکل زیر مواجه می گردید:
- تداخل نام ها یا همان name collision بین کدهایی که شما ساخته اید با کلاس ها، توابع، ثوابت PHP یا با کلاس ها، توابع یا ثابت های یک برنامه third-party
- ایجاد اشکال ددر هنگام کوتاه کردن (استفاده از alias) نام های بلند یا همان Extra_Long_Names که باعث افزایش خوانایی یا readability کد های شما خواهد شد.
برای جلوگیری از name collision یا همان تداخل نام برای class ها، function ها و constant های هم نام، از مفهوم namespace در PHP استفاده می شود.
در واقع namespace ها راهی را برای گروه بندی کلاس ها، interface ها، تابع ها و ثابت های مرتبط را به ما می دهند.
در صورتی که دو کلاس یا متد (یا کلاس و متد) داشته باشیم که دارای نام های یکسان باشند، برای جلوگیری از تداخل آن ها باید از namespace جداگانه در قبل تعریف کلاس، استفاده کنیم.
برای تعریف namespace کافی است پیش از عبارت namespace و سپس نام آن استفاده کنیم. در صورتی که namespace از چند بخش (یعنی از دایرکتوری های تو در تو) تشکیل شده باشد، برای جداسازی آن از علامت \ استفاده می کنیم.
برای صدا کردن متد ها یا ساخت اشیا از کلاس دارای namespace، می باید نام namespace به همراه علامت بک اسلش فراخوانی شده و بعد از آن، نام متد آورده شود.
class MsnClass {} function msnfunction() {} const MSNCONST = 1; $a = new MsnClass; $c = new \my\msn\MsnClass; // see "Global Space" section $a = strlen('hi'); // see "Using namespaces: fallback to global function/constant" section $d = namespace\MSNCONST; // see "namespace operator and __NAMESPACE__ constant" section $d = __NAMESPACE__ . '\MSNCONST'; echo constant($d); // see "Namespaces and dynamic language features" section
استفاده از best practice ها برای namespace در PHP:
همان طور که می دانید، best practice ها با نام PHP Standard Recommendation یا به اختصار PSR ها شناخته می شوند.
برای دیدن لیست PSR ها در پی اچ پی، می توانید از این لینک استفاده کنید. در حال حاضر ۵ بخش کلی برای PSR ها با نام های PSR-0 و PSR-1 و PSR-2 و PSR-3 و PSR-4 آن ها را می شناسیم.
در حال حاضر PSR-0 و PSR-4 به مباحث حل مشکلات تداخل نام ها و استفاده از namespace برای FQCN می پردازد.
FQCN یا Fully Qualified Class name می باشد. در واقع این اصطلاح به مجموع full namespace + class name گفته می شود. این امر باعث بهبود در زمینه autoloading می باشد.
استاندارد هایی که در PSR-0 و PSR-4 برای namespacing تعریف شده، به شما اجازه می دهند تا path خود را به یک FQCN معتبر یا valid تبدیل کنید.
فرض کنید شما یک ساختار به فرم زیر دارید و می خواهید مفهوم autoloading را با در نظر گرفتن namespace های آن، پیاده سازی کنید:
Structure : {path}/autoloader.php {path}/index.php {path}/src/Msn/Tools/MsnTool.php
فایل ها را به صورت جداگانه در زیر قرار داده ایم. فایل اول، index.php می باشد که فایل autoloader.php خود را در آن include می کنیم. پس از آن به راحتی می توانیم از کلاس MsnTool استفاده کنیم (بدون اینکه دچار fatal error بشویم)
// {path}/src/Msn/Tools/MsnTool.php namespace Msn\Tools; class MsnTool {}
// {path}/index.php include 'autoloader.php'; $tool = new Msn/Tools/MsnTool();
// {path}/autoloader.php function loadClass($className) { $fileName = ''; $namespace = ''; // Sets the include path as the "src" directory $includePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'src'; if (false !== ($lastNsPos = strripos($className, '\\'))) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; $fullFileName = $includePath . DIRECTORY_SEPARATOR . $fileName; if (file_exists($fullFileName)) { require $fullFileName; } else { echo 'Class "' . $className . '" does not exist.'; } } spl_autoload_register('loadClass'); // Registers the autoloader
استفاده از namespace alias در PHP:
گاهی اوقات مسیرهای ما طولانی شده و این باعث طولانی شدن namespace های ما می باشد. استفاده از alias ها باعث می گردد که یک namespace طولانی را به یک نام خلاصه شده تبدیل کنیم.
با استفاده از alias به جای استفاده از namespace ، از نام خلاصه آن با استفاده از کلمات کلیدی use و as به صورت زیر استفاده می کنیم.
use Msn\Library01 as L; use Msn\Library02\MsnClass as Obj; header('Content-type: text/plain'); require_once('library01.php'); require_once('library02.php'); echo L\MsnCONST . "\n"; echo L\MsnFunction() . "\n"; echo L\MsnClass::msnmethod() . "\n"; echo Obj::msnmethod() . "\n";
بخش هشتم: مفهوم Trait در PHP
زبان هایی چون ++C و پایتون، زبان هایی هستند که از وراثت چندگانه یا همان Multi Inheritance پشتیبانی می کنند. اما زبان PHP از وراثت چندگانه پشتیبانی نمی کند. برای رفع این مشکل و پیاده سازی مکانیزمی برای استفاده از مجدد از کدهای تکراری در زبان single inheritance از مفهوم trait استفاده می شود.
درواقع trait محدودیت های موجود در وراثت یگانه را برداشته و توسعه دهنده می تواند آزادانه از چندین کلاس مختلف که در ساختار سلسه مراتبی کلاسی مختلف قرار دارند، در کلاس های خود استفاده کند.
در واقع مفهوم trait باعث کم شدن پیچیدپی های و جلوگیری از مشکلات رایج مربوط با وراثت چندگانه و Mixin ها می گردد.
trait ها بسیار شبیه کلاس هستند، با این تفاوت که از آن ها نمی تواند ارث برد اما می توان از آن ها در کلاس ها به راحتی استفاده کرد. در واقع به نوعی می توان در جاهایی که نیاز داریم به جای مفهوم is-a در شی گرایی از مفهوم has-a یا همان composition استفاده کنیم، از trait استفاده می کنیم.
برای استفاده از trait کافی به جای کلمه کلیدی class از کلمه کلیدی trait استفاده کنیم. همچنین برای استفاده trait، کافی است از کلمه کلیدی use در داخل کلاس استفاده نماییم.
استفاده از trait به صورت ساده در PHP
فرض کنید شما یک کد برای لاگ کردن در بخش های مختلف سیستم دارید. حال شما می خواهید هم آن را در کلاس حساب بانکی استفاده کنید و هم در کلاس user. برای اینکار به صورت زیر عمل می کنید:
trait Logger { function log($msg) { echo '<pre>'; echo date('Y-m-d h:i:s') . ':' . '(' . __CLASS__ . ') ' . $msg . '<br/>'; echo '</pre>'; } } class BankAccount { use Logger; private $accountNumber; function __construct($accountNumber) { $this->accountNumber = $accountNumber; $this->log("A new $accountNumber bank account created"); } } class User { use Logger; function __construct() { $this->log("A new user created"); } } $account = new BankAccount('1234567674'); $user = new User();
استفاده از Multiple trait یا trait چندگانه در PHP
در مثال زیر، شما یک کلاس IDE دارید و از چندین trait در داخل آن استفاده می کنید:
trait Preprocessor { function preprocess() { echo 'Preprocess...done' . '<br/>'; } } trait Compiler { function compile() { echo 'Compile code... done' . '<br/>'; } } trait Assembler { function createObjCode() { echo 'Create the object code files... done.' . '<br/>'; } } trait Linker { function createExec() { echo 'Create the executable file...done' . '<br/>'; } } class IDE { use Preprocessor, Compiler, Assembler, Linker; function run() { $this->preprocess(); $this->compile(); $this->createObjCode(); $this->createExec(); echo 'Execute Soosis Bandari...done' . '<br/>'; } } $ide = new IDE(); $ide->run();
Composition یا ترکیب کردن trait ها با هم در Multiple traits
از دیگر موارد جالب، ترکیب کردن چندین trait و استفاده از آن ها در یک trait دیگر و سپس استفاده آن در یک کلاس می باشد. مثال زیر این مورد را نشان می دهد:
trait Reader { public function read($source) { echo sprintf("Read from %s <br/>", $source); } } trait Writer { public function write($destination) { echo sprintf("Write to %s <br/>", $destination); } } trait Copier { use Reader, Writer; public function copy($source, $destination) { $this->read($source); $this->write($destination); } } class FileUtil { use Copier; public function copyFile($source, $destination) { $this->copy($source, $destination); } }
بخش نهم: کامنت گذاری با استفاده از DocBlocks در PHP
برای کامنت گذاری کلاس ها در PHP می توانیم از استایل DocBlock استفاده کنیم. بسیاری از IDE های پر استفاده مانند PhpStorm یا Eclipse یا Netbeans از این روش برای تولید خودکار کامنت در کلاس ها، استفاده می کنند.
قدرت واقعی DocBlock ها در توانایی استفاده از tag ها می باشد که با علامت @ شروع می شوند. به این وسیله برنامه نویس می تواند اطلاعات اضافی در مورد بخش های مختلف کلاس را در کد خود، نشانه گذاری و تشریح نمایید.
پر استفاده ترین تگ ها عبارتند:
- author@
- copyright@
- license@
- var@
- param@
- return@
مثال زیر این مورد را به خوبی نمایش می دهد.
/** * A simple class * * This is the long description for this class, * which can span as many lines as needed. It is * not required, whereas the short description is * necessary. * * It can also span multiple paragraphs if the * description merits that much verbiage. * * @author Jason Lengstorf <jason.lengstorf@ennuidesign.com> * @copyright 2010 Ennui Design * @license http://www.php.net/license/3_01.txt PHP License 3.01 */ class SimpleClass { /** * A public variable * * @var string stores data for the class */ public $foo; /** * Sets $foo to a new value upon class instantiation * * @param string $val a value required for the class * @return void */ public function __construct($val) { $this->foo = $val; } /** * Multiplies two integers * * Accepts a pair of integers and returns the * product of the two. * * @param int $bat a number to be multiplied * @param int $baz a number to be multiplied * @return int the product of the two parameters */ public function bar($bat, $baz) { return $bat * $baz; } }
مقایسه اشیا در PHP
در PHP شما می توانید اشیا را باهم مقایسه کنید. از این کار به عنوان PHP Compare Object یاد می شود.
مقایسه اشیا با استفاده از عامل (==) یا comparison operator در PHP
زمانی که شما از عامل == برای مقایسه دو شی در PHP استفاده می کنید، دو object باهم برابر خواهند بود در صورتی که هر دو نمونه از یک کلاس instantiate شده باشند و همچنین دارای property ها و مقدار یکسان باشند.
class Point { private $x; private $y; public function __construct($x, $y) { $this->x = $x; $this->y = $y; } /** * Compare two points * @param Point $p1 * @param Point $p2 * @return boolean return true if two points are equal, otherwise returns false */ public static function compare($p1, $p2) { return $p1 == $p2; } public function getX() { return $this->x; } public function setX($x) { $this->x = $x; } public function getY() { return $this->y; } public function setY($y) { $this->y = $y; } } $p1 = new Point(10, 20); $p2 = new Point(10, 20); if (Point::compare($p1, $p2)) { echo 'p1 and p2 are equal <br/>'; } else { echo 'p1 and p2 are not equal <br/>'; }
مقایسه اشیا با استفاده از عامل (===) یا identity operator در PHP
زمانی که شما از عامل === برای مقایسه دو شی در PHP استفاده می کنید، دو object باهم برابر خواهند بود در صورتی که هر دو نمونه به یک شی از آن کلاس اشاره کنند.
نتیجه گیری برای مقاله آموزش شی گرایی در PHP
این مقاله به عنوان یک مرجع در آموزش شی گرایی می تواند مورد استفاده قرار گیرد. دراین مقاله به طور کلی هم با مفاهیم شی گرایی و هم با نحوه این پیاده سازی مفاهیم شی گرایی در PHP صحبت کردیم.
در ابتدا با مفاهیم شی و کلاس و خاصیت ها و متدهای آن آشنا شدیم. سپس به بررسی پیاده سازی آن ها در شی گرایی پرداختیم.
در ادامه سطح دسترسی به کلاس ها، خاص و متدهای آن را بررسی کردیم. در ادامه به بررسی متدهای زنجیره ای و متدهای جادویی در پی اچ پی پرداختیم.
سپس با مفاهیم ارث بری و وراثت در PHP و نحوه پیاده سازی آن آشنا شدیم. سپس مفاهیم abstract و interface را تشریح کردیم و در ادامه نشان دادیم که چگونه می توان پولی مورفیسم را در PHP پیاده سازی کرد.
سپس در مورد کپسوله سازی یا همان encapsulation توسط name space ها صحبت کردیم. در انتها نیز به مفاهیم triat و نحوه کامنت گذاری استاندارد در کلاس و مقایسه اشیا باهم پرداختیم.
ممکن است شما موارد بیشتری را بدانید که ما فراموش کرده ایم تا در این مقاله قرار دهیم.
اگر شما از این موارد آگاه هستید، حتما در بخش نظرات عنوان کنید تا آن را به مقاله “آموزش شی گرایی در PHP” اضافه کنیم. در ضمن اگر این مقاله را مفید دیدید، حتما آن را به دوستان خود معرفی کرده یا در شبکه های اجتماعی به اشتراک بگذارید.
راهنما برای مطالعه بیشتر:
برای تولید مقاله ثابت ها در php ، از لینک های زیر استفاده شده است که برای مراجعه به آن ها می توانید از لیست زیر استفاده کنید:
راهنما برای خواندن سایر مقالات سایت به صورت دسته بندی شده:
شما می توانید از طریق لینک های کاربردی زیر به سایر مقالات سایت که کاملا بصورت طبقه بندی شده وجود دارد، مراجعه نموده و از آن ها استفاده کنید:
با سلام.آموزش بسیار خوبی هست.خسته نباشید
سلام به شما دوست عزیز
بسیار ممنونم که وقت با ارزش خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
سپاس فراوان و خوشحالیم از اینکه این مطلب مورد پسند شما قرار گرفته است.
با سلام
واقعا آموزش کامل و خیلی خوبی بود. ممنون
سلام به شما دوست عزیز
نظر لطف شماست
ممنون هستم که وقت با ارزش خود را گذاشتید تا برای ما پیام ارسال کنید
سپاس فراوان
مهندس مفید بود
سلام
ممنونم، تشکر فراوان
مقاله فوق العاده مفید و کاملا کاربردی بیشتری ابهاماتی که درباره کلاس های ابسترک و اینترفیس ها داشتم بر طرف شد و همچنین مفهوم بعضی از کلاس ها و متد هایی که استفاده میکردم رو با این مقاله خوبتون متوجه شدم . دستتون درد نکنه و خسته نباشید بابت این مقاله فوق العاده مفید .
ای کاش درباره متد ها و کلاس های وردپرس هم مثل این مقاله روی سایتتون منتشر می کردین .
سلام به شما دوست عزیز
بسیار سپاسگزارم که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
بسیار خوشحالم که این مقاله توانسته نیازهای شما رو برآورده بکنه.
پیام های دلگرم کننده شما، قطعا باعث ادامه راه توسط ما خواهد شد.
بابت وردپرس هم در برنامه امسال مون در شش ماه دوم سال هست. در خبرنامه ثبت نام کنید تا حتما پیام های انتشار مقالات سایت، به شما اطلاع داده بشه.
سپاس فراوان
بسم الله الرحمن الرحیم
سلام علیکم
خیلی عالی بود قلم خوبی دارید
از خدای متعال می خواهم بتوانید شکر نعمت قلم خوب رو به جا آورید.
سلام به شما دوست عزیز
از شما بسیار ممنونم که وقت ارزشمند خودتون رو گذاشتید، تا پیام های دلگرم کننده خودتون رو، برای ما ارسال کنید.
نظر لطف شماست. بسیار خوشحالم که این مطلب مورد توجه شما قرار گرفته است.
برای شما بهترین را آرزومندم.
سپاس فراوان
سلام. خیلی ممنون بابت این مقاله. بسیار کاربردی و مفید بود. سپاس فراوان و خسته نباشید.
سلام به شما دوست عزیز
سپاسگزارم. نظر لطف شماست.
پیام های دلگرم کننده شما باعث ادامه راه توسط ما خواهد شد.
سپاس فراوان
فوق العاده جامع و پرمحتوا و مفید بود.سپاس فراوان بابت زحمات تون.آرزوی موفقیت وسلامتی براتون دارم.پایدار باشد.
سلام به شما دوست عزیز
نظر لطف شماست.
از شما بسیار سپاسگزارم که وقت ارزشمند خودتان را گذاشتید تا برای ما پیام ارسال کنید.
خوشحالیم که محتوا برای شما ارشمنده بوده است.
تشکر و سپاس فراوان
بسیار عالی بود
با سلام به شما دوست عزیز
خوشحالیم که این مقاله آموزشی مورد توجه شما واقع شد.
پیام های دلگرم کننده شما باعث ادامه راه توسط ما خواهد شد.
از لطف شما ممنون و سپاسگزارم
بینظیر بود!
خسته نباشید
سلام به شما دوست عزیز
بسیار خوشحالم که مورد توجه شما واقع شده. به زودی فیلم این بخش رو هم در همین صفحه قرار خواهیم داد.
با تشکر از نظرات دلگرم کننده همیشگی شما
تا حالا هیپ مقاله ی جامعی به این خلاصه ای و واضحی در مورد oop در php ندیده بودم
موفق باشی رفیق
سلام
نظر لطف شماست
ممنونم بابت گذاشتن پیام محبت آمیز شما
درود. فوق العاده بود. سپاس. موفق،سلامت و شاد باشید استاد
سلام به شما دوست عزیز
از لطف و محبت شما کمال سپاس و تشکر رو دارم
ممنون که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید
ممنونم
سلام چندین روز پای مقالتون بودم مطالعه کردم واقعا مفید و کامل بود فقط چون مبتدی ام بخشی از کدنویسی ها توضیحش کم بود نمی فهمیدم با تشکر از شما
سلام به شما دوست عزیز
نظر لطف شماست
امیدوارم این آموزش ها مورد استفاده شما قرار گرفته باشند.
ممنونم از اینکه وقت با ارزش خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
از لطف شما بسیار ممنون و سپاسگزارم
خیلی عالی و بی نظیر خدایی تو این دور زمونہ کسی بدون پول کاری نمکینہ ولی شما این ھمہ وقت و تلاش اونم free of cost ۔۔۔۔ highly appreciate you for your word and efforts just keep it up and we will support you
سلام به شما دوست عزیز
نظر لطف شماست. از دید خودم هنوز باز یک جاهایی از این مقاله نیاز داره تا کامل بشه. حتما در فرصت هایی آتی، باز هم اون رو آپدیت خواهم کرد.
ممنون از شما که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
نظرات دلگرم کننده شما، باعث میشه این راه رو پر قدرت تر جلو بریم.
سپاس فراوان از شما
سلام
واقعا ممنون
اجرت با امام حسین.
زکات علم همینه.واقعا ممنون.
انشاا… همیشه در مسیر پیشرفت و موفقیت باشید.
سلام
از لطف شما سپاسگزارم. نظر لطف شماست.
خوشحالم که مورد استفاده شما قرار گرفته. پیام های دلگرم کننده شما باعث ادامه راه توسط تیم ما خواهد شد.
از شما ممنونم که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
سپاس فراوان
واقعا ممنونم از شما، خدا خیرتون بده بسیار کمکم کرد، اسم شما همیشه یادم میمونه
سلام به شما مهرزاد عزیز
بسیار خوشحالم که این مقاله به شما کمک کرده. هدفم هم همیشه در مقاله های ارائه شده در سایت همین بوده.
نظرات بسیار دلگرم کننده شما، باعث خواهد شد که در این راه محکم تر قدم برداریم.
از لطف شما بسیار ممنونم که وقت ارزشمند خودتون رو گذاشتید تا پیام های محبت آمیز خودتون رو برای ما ارسال کنید.
ازتون کمال سپاس و تشکر رو دارم.
با سلام و احترام
سپاس از این همه معرفت .دست شما رو میبوسم استاد
اصلا ممکنه کسی این مقاله رو بخونه و تشکر نکنه ؟
با عرض سلام خدمت شما دوست عزیز و محترم
خواهش می کنم من رو شرمنده خودتون نکنید. همین که این مقاله مورد استفاده شما قرار گرفته، برای من بسیار ارزشمند هست.
ازتون ممنونم که وقت بسیار ارزشمند خود رو گذاشتید تا پیام های محبت آمیزتون رو برای ما ارسال کنید.
کمال سپاس و تشکر رو دارم و بازهم از شما ممنونم
سلام خدمت شما
جا داره تشکر کنم بابت این پست بسیار مفید. واقعا همونطور که دوستمون گفتن نظیر نداره. برخلاف ترجمه و کپی های رایج بسیار ضعیف فارسی، این مطلب عالی بود از هر نظر، شیوایی، رعایت ترتیب ذکر مطالب و اشاره و توضیحات در مورد جزئی ترین بخش ها.
کمال تشکر و قدردانی از شما جناب مهندس سلطانی نشان.
موفق و سربلند باشید.
سلام خدمت شما دوست عزیز
واقعا خوشحالم که این پست مورد رضایت دوستان قرار گرفته. واقعیت دنبال گذاشتن مرجعی برای شی گرایی بودم که حتی اگر خودم هم نیاز داشتم، بتونم به اون مراجعه کنم. بنابراین سعی کردم تا حد امکان اون رو کامل تهیه کنم.
خوشحال هستم از اینکه بعد از چندین وقت که از زمان انتشار گذشته، مورد استفاده دوستانی چون شما قرار گرفته.
پیام های محبت آمیز شما باعث میشه که مسلما در این راه بهتر گذشته عمل کنیم و سعی داشته باشیم که با حفظ روال قبلی، مطالب بهتری رو ارائه بدیم.
از اینکه وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید از شما کمال سپاس و تشکر رو دارم.
سپاس فراوان
با سلام. واقعا کامل تر از این مقاله ندیدم. بی نظیر بود. از شما واقعا متشکرم.
سلام به شما دوست عزیز
ممنون از پیام های دلگرم کننده شما. پیام های محبت آمیز شما باعث میشه بتونیم همچنان به راه خودمان ادامه بدیم.
از لطف شما بسیار سپاسگزارم که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام بفرستید.
سپاس فراوان
بسیار عالی و کامل . ممنون