آموزش شی گرایی در 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 ، مفاهیمی هستند که خیلی اوقات اشتباه توسط توسعه دهندگان به کار برده می شوند.
همانگونه که در عکس می بینید، یک کلاس می تواند یک طرح کلی و اولیه از یک خانه باشد (یا همان 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>";
//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";
//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>'; }
//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();
نکته مهم در مورد متغیرها و متدهای استاتیک
برای استفاده از متغیرها و متدهای یک کلاس، حتما می باید یک شی از آن ساخته شود اما برای استفاده از متغیر یا متد استاتیک، نیازی به ساخت یک شی نیست. در واقع برای بار اول که کلاس در حافظه ایجاد می گردد یا 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 و یا بالعکس، دسترسی داشتیم و امکان تغییر در خارج از آن وجود نداشته باشد.
همچنین اکثر متدها برای دسترسی به رفتار یک شی، به صورت عمومی تعریف می شوند. البته این بسته به نوع طراحی کلاس ممکن است متفاوت باشد. بر مبنای همین موارد، سه نوع دسترسی به متغیر ها و متدهای یک کلاس در پی اچ پی، تعریف شده است.
شما با استفاده از کلمات کلیدی زیر، می توانید نحوه دسترسی به یک کلاس را کنترل نمایید:
چرا باید از 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 و همین طور علامت <- استفاده می شود. مفاهیم گفته شده به صورت خلاصه در زیر تشریح شده است:
//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
//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);
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'; } }
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 */
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');
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 */
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 نکاتی وجود دارد که در زیر به آن ها اشاره شده است:
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 */
/***** 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 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(); }
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 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 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) { } }
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
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
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 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();
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();
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 یاد می شود.
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/>'; }
نتیجه گیری برای مقاله آموزش شی گرایی در 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
سلام به شما دوست عزیز
نظر لطف شماست. از دید خودم هنوز باز یک جاهایی از این مقاله نیاز داره تا کامل بشه. حتما در فرصت هایی آتی، باز هم اون رو آپدیت خواهم کرد.
ممنون از شما که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
نظرات دلگرم کننده شما، باعث میشه این راه رو پر قدرت تر جلو بریم.
سپاس فراوان از شما
سلام
واقعا ممنون
اجرت با امام حسین.
زکات علم همینه.واقعا ممنون.
انشاا… همیشه در مسیر پیشرفت و موفقیت باشید.
سلام
از لطف شما سپاسگزارم. نظر لطف شماست.
خوشحالم که مورد استفاده شما قرار گرفته. پیام های دلگرم کننده شما باعث ادامه راه توسط تیم ما خواهد شد.
از شما ممنونم که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید.
سپاس فراوان
واقعا ممنونم از شما، خدا خیرتون بده بسیار کمکم کرد، اسم شما همیشه یادم میمونه
سلام به شما مهرزاد عزیز
بسیار خوشحالم که این مقاله به شما کمک کرده. هدفم هم همیشه در مقاله های ارائه شده در سایت همین بوده.
نظرات بسیار دلگرم کننده شما، باعث خواهد شد که در این راه محکم تر قدم برداریم.
از لطف شما بسیار ممنونم که وقت ارزشمند خودتون رو گذاشتید تا پیام های محبت آمیز خودتون رو برای ما ارسال کنید.
ازتون کمال سپاس و تشکر رو دارم.
با سلام و احترام
سپاس از این همه معرفت .دست شما رو میبوسم استاد
اصلا ممکنه کسی این مقاله رو بخونه و تشکر نکنه ؟
با عرض سلام خدمت شما دوست عزیز و محترم
خواهش می کنم من رو شرمنده خودتون نکنید. همین که این مقاله مورد استفاده شما قرار گرفته، برای من بسیار ارزشمند هست.
ازتون ممنونم که وقت بسیار ارزشمند خود رو گذاشتید تا پیام های محبت آمیزتون رو برای ما ارسال کنید.
کمال سپاس و تشکر رو دارم و بازهم از شما ممنونم
سلام خدمت شما
جا داره تشکر کنم بابت این پست بسیار مفید. واقعا همونطور که دوستمون گفتن نظیر نداره. برخلاف ترجمه و کپی های رایج بسیار ضعیف فارسی، این مطلب عالی بود از هر نظر، شیوایی، رعایت ترتیب ذکر مطالب و اشاره و توضیحات در مورد جزئی ترین بخش ها.
کمال تشکر و قدردانی از شما جناب مهندس سلطانی نشان.
موفق و سربلند باشید.
سلام خدمت شما دوست عزیز
واقعا خوشحالم که این پست مورد رضایت دوستان قرار گرفته. واقعیت دنبال گذاشتن مرجعی برای شی گرایی بودم که حتی اگر خودم هم نیاز داشتم، بتونم به اون مراجعه کنم. بنابراین سعی کردم تا حد امکان اون رو کامل تهیه کنم.
خوشحال هستم از اینکه بعد از چندین وقت که از زمان انتشار گذشته، مورد استفاده دوستانی چون شما قرار گرفته.
پیام های محبت آمیز شما باعث میشه که مسلما در این راه بهتر گذشته عمل کنیم و سعی داشته باشیم که با حفظ روال قبلی، مطالب بهتری رو ارائه بدیم.
از اینکه وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام ارسال کنید از شما کمال سپاس و تشکر رو دارم.
سپاس فراوان
با سلام. واقعا کامل تر از این مقاله ندیدم. بی نظیر بود. از شما واقعا متشکرم.
سلام به شما دوست عزیز
ممنون از پیام های دلگرم کننده شما. پیام های محبت آمیز شما باعث میشه بتونیم همچنان به راه خودمان ادامه بدیم.
از لطف شما بسیار سپاسگزارم که وقت ارزشمند خودتون رو گذاشتید تا برای ما پیام بفرستید.
سپاس فراوان
بسیار عالی و کامل . ممنون