دوستان عزیز سلام ، آیا با مفهوم کلاس و شی آشنایی دارید؟ اگر بخواهید در این زمینه بیشتر بدانید با اموزش امروز ما همراه باشید .تصور کنید دنیایِ ما از اشیا و چیزهای متفاوتی همچون خورشید، زمین، ماه و غیره تشکیل شده. به طور مشابه، می توانید تصور کنید که ماشین شما از چیزهای مختلفی از جمله فرمان، چرخ، دنده و غیره تشکیل شده. همین طور، هم مفاهیم برنامه نویسی شی گرا {object oriented} وجود دارند که همه چیز را شی می پندارند و یک برنامه را با کمک همین اشیا اجرا می کنند.

مفاهیم شی گرا

پیش از پرداختن به جزئیات، اجازه دهید واژه ها و مفاهیم مهم مربوط به برنامه نویسی شی گرا را توضیح دهیم.

class{کلاس} : نوع داده ای است که توسط برنامه ساز تعیین می شود، که علاوه بر تابع های محلی، اطلاعات محلی را نیز شامل می شود. کلاس مانند الگویی است که موارد مشابهی از همان نوع شی را می توانید بر اساس آن بسازید.

object{شی} :  شی تک نمونه ای است از ساختار اطلاعات که کلاس تعیین می کند. ابتدا یک کلاس تعریف می کنید، سپس شی های متعلق به آن را می سازید. به شی {object} نمونه {instance} نیز می گویند.

member variable {متغیر عضو} : این ها متغیرهایی هستند که داخل یک کلاس تعریف می شوند. به این اطلاعات فقط می توان از طریق تابع های عضو {member function} دسترسی پیدا کرد و برای هر چیز دیگری خارج از کلاس غیر قابل مشاهده است. پس از این که شی ساخته می شود، متغیرهای ذکر شده به عنوان خصیصه یا ویژگی {attribute} آن شی شناخته می شوند.

member function {تابع عضو} : این توابع در کلاس معرفی می شوند و از آن ها به منظور دستیابی به اطلاعات شی {object information} استفاده می شود.

Inheritance {وراثت} : به فرآیندی گفته می شود که طی آن یک کلاس با به ارث بردن تابع از کلاس والد {parent class} به وجود می آید . کلاس فرزند {child class}  تعدادی یا همه ی توابع و متغیرهای کلاس والد را به ارث می برد.

parent class {کلاس والد} : کلاسی که کلاس دیگری چیزی را از آن به ارث می برد، به آن کلاس اصلی، پایه {base، super class} نیز گفته می شود.

child class {کلاس فرزند} : کلاسی که از کلاس دیگر چیزی را به ارث می برد. به آن زیر کلاس یا کلاس مشتق {sub، derived class} نیز می گویند.

Polymorphism {چند شکلی} : مفهوم شی گرایست که در آن از یک تابع می توان برای اهداف گوناگون بهره برد. برای مثال، اسم تابع {function name} ثابت می ماند، ولی به تعداد مختلفی آرگومان {argument} نیاز دارد و کارهای متفاوتی را می تواند انجام دهد.

overloading {اضافه بار زدن} : نوعی polymorphism که در آن همه یا برخی از عملگرها {operator}  بسته به نوع آرگومان هایشان، پیاده سازی متفاوتی دارند. توابع هم به طور مشابه ممکن است با پیاده سازی های {implementations} متفاوت overload شوند.

data abstraction {حذف داده} : هر گونه نمایش داده که در آن جزئیات پیاده سازی پنهان {حذف شده} باشد.

Encapsulation {خلاصه، ادغام { : اشاره به مفهوم ادغام تمام اطلاعات و توابع عضو با هم برای تشکیل یک شی واحد دارد.

Constructer{تابع سازنده} : به گونه ی خاصی تابع که خودکار به هنگام شکل گیری یک شی در کلاس فراخوانده می شود اشاره دارد.

Destructor {مخرب ها} :  به گونه ی خاصی تابع که خودکار به هنگام پاک شدن یا از دامنه خارج شدن یک شی فراخوانده می شود اشاره دارد.

تعریف کلاس های PHP

فرم کلی تعریف یک کلاس جدید در PHP به شرح زیر می باشد.

‎<?php‎

class phpClass{‎

‎   var $var1;‎

‎   var $var2 = “constant string”;‎

‎   function myfunc ($arg1‎، ‏‎ $arg2) {‎

‎      [. . ]‎

‎   }‎

‎   [. . ]‎

‎}‎

‎?>‎

توصیف هر خط  را در زیر مشاهده می کنید.

فرم خاص کلاس، که به دنبال آن اسم کلاسی که قصد دارید تعریف کنید.

مجموعه آکولادی {} که شمار زیادی تعریف متغیر و تابع تعریف شده را در خود دارد.

تعریف متغیر ها که به شکل خاص var آغاز می شود، که به دنبال آن با قرارداد $ و اسم متغیر {variable name} می آید، حتی ممکن است به مقدار ثابت {constant value} یک مقدار اولیه داده شود.

تعاریف تابع {function definition} شباهت زیادی به توابع مستقل PHP دارند ولی بومی کلاس هستند و از آن ها برای دستیابی و تعیین object data استفاده می شود.

مثال

مثال زیر یک کلاس {دسته} از نوع کتاب ها را به شکل زیر تعریف می کند.

‎<?php‎

class  Books{‎

‎    /* Member variables */‎

‎    var $price;‎

‎    var $title;‎

‎    /* Member functions */‎

‎    function setPrice($par){‎

‎       $this->price = $par;‎

‎    }‎

‎    function getPrice(){‎

‎       echo $this->price . “

‎”;‎

‎    }‎

‎    function setTitle($par){‎

‎       $this->title = $par;‎

‎    }‎

‎    function getTitle(){‎

‎       echo $this->title . “

‎”;‎

‎    }‎

‎}‎

‎?>‎

متغیر  $this یک متغیر خاص است که به همان شی {object} اشاره دارد یعنی خودش.

ساختن شی {object} درPHP

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

مثال زیر چگونگی ساختن یک شی با استفاده از عملگر new را نشان می هد.

‎  $physics = new Books;‎

‎   $maths = new Books;‎

‎   $chemistry = new Books;‎

در اینجا سه شی ساخته ایم که از یکدیگر مستقل هستند و موجودیتشِان از هم کاملاً جدا هست. در مرحله ی بعد، شیوه ی دست یافتن به تابع عضو و پردازش مقادیر عضو {member value} را نمایش خواهیم داد.

فراخواندن توابع عضو {member function}

پس از به وجود آوردن شی {object}، می توانید توابع عضو مرتبط با آن شی را فرا بخوانید. یک تابع         عضو {member function} فقط می تواند مقدار عضو {member value} شی مرتبط با آن را پردازش کند.

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

‎  $physics->setTitle( “Physics for High School” );‎

‎   $chemistry->setTitle( “Advanced Chemistry” );‎

‎   $maths->setTitle( “Algebra” );‎

‎   $physics->setPrice( 10 );‎

‎   $chemistry->setPrice( 15 );‎

‎   $maths->setPrice( 7 );‎

حال برای به دست آوردن مقادیر تنظیم شده در مثال بالا ، تابع عضو دیگری را فرا می خوانید.

‎$physics->getTitle();‎

‎   $chemistry->getTitle();‎

‎   $maths->getTitle();‎

‎   $physics->getPrice();‎

‎   $chemistry->getPrice();‎

‎   $maths->getPrice();‎

نتیجه ی زیر به دست می آید.

Physics for High School

‎  Advanced Chemistry

‎  Algebra

‎  ۱۰‎

‎  ۱۵‎

‎  ۷‎

توابع سازنده

گونه ی خاصی تابع که خودکار به هنگام شکل گیری یک شی فراخوانده می شود. با مقدار دهی اولیه {initializing} توسط تابع سازنده می توانیم از این رفتار نهایت استفاده را ببریم.

PHP برای تعریف یک سازنده ، تابع مخصوصی به نام __construct() را ارائه می دهد. شما می توانید هر تعداد آرگومان که دوست دارید به تابع سازنده بفرستید.

مثال زیر یک سازنده برای کلاس کتاب ها فراهم می سازد و قیمت و عنوان کتاب را به هنگام خلق شدن شی مقدار دهی اولیه {initialize} می کند.

function __construct( $par1‎، ‏‎ $par2 ){‎

‎   $this->price = $par1;‎

‎   $this->title = $par2;‎

‎}‎

نیازی نیست که برای انتخاب و تنظیم قیمت و عنوان کتاب، تابع را جداگانه فرابخوانید. فقط می توانیم این دو متغیر عضو را هنگام به  وجود آمدن شی، مقداردهی کنیم. به مثال زیر دقت کنید.

‎   $physics = new Books( “Physics for High School”‎، ‏‎ ۱۰ );‎

‎   $maths = new Books ( “Advanced Chemistry”‎، ‏‎ ۱۵ );‎

‎   $chemistry = new Books (“Algebra”‎، ‏‎ ۷ );‎

‎   /* Get those set values */‎

‎   $physics->getTitle();‎

‎   $chemistry->getTitle();‎

‎   $maths->getTitle();‎

‎   $physics->getPrice();‎

‎   $chemistry->getPrice();‎

‎   $maths->getPrice();‎

نتیجه ی زیر حاصل می گردد.

‎  Physics for High School

‎  Advanced Chemistry

‎  Algebra

‎  ۱۰‎

‎  ۱۵‎

‎  ۷‎

تابع مخرب

درست مثل تابع سازنده، می توانید تابع مخرب را به کمک __destruct() تعریف کنید. می توانید تمام منابع را درون حیطه ی یک مخرب منتشر کنید.

وراثت

تعاریف کلاس{class definition} می تواند به دلخواه و به کمک بند توسعه یافته {extended clause} از تعریف کلاس والد{parent class definition}  ارث ببرد. دستور نحوی {syntax}  آن به شکل زیر است.

class Child extends Parent {‎

‎  }‎

اثر فرآیند وراثت باعث می شود که کلاس فرزند ویژگی های زیر را داشته باشد.

به طور خود کار تمام معرفی های متغیرهای عضو {member variable declaration} کلاس والد را دارا می باشد.

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

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

class Novel extends Books{‎

‎   var publisher;‎

‎   function setPublisher($par){‎

‎     $this->publisher = $par;‎

‎   }‎

‎   function getPublisher(){‎

‎     echo $this->publisher.  “

‎”;‎

‎   }‎

‎}‎

حال جدا از تابع های به ارث برده،  class Novelدو تابع دیگر را هم حفظ می کند.

باطل کردن یا برتری جستن بر تابع {function overriding}

تعاریف توابع {function definition} در کلاس فرزند، تعاریفی که در کلاس والد همین اسم را دارند را باطل {override} می کند. در کلاس فرزند، می توانیم تعریف یک تابع به ارث رسیده از کلاس والد را اصلاح کنیم.

همان طور که در مثال زیر می بینید دو تابع getPrice  و getTitle هر دو برای به دست آمدن تعدادی value باطل یا لغو شده اند.

‎  function getPrice(){‎

‎       echo $this->price .  “
‎”;‎
‎       return $this->price;‎

‎    }‎

‎    function getTitle(){‎

‎       echo $this->title .  “
‎”;‎
‎       return $this->title;‎

‎    }‎

اعضای عمومی

مگر این که از پیش خلاف آن را مشخص کرده باشید، خصوصیات و متد های یک کلاس عمومی خواهد شد. به این معنا که، درسه شرایط ممکن زیر می توان به آن دسترسی پیدا کرد.

خارج از کلاسی که در آن تعریف شده.

از داخل کلاسی که در آن تعریف شده.

از داخل یک کلاس دیگر که کلاسی را که در آن تعریف می شود اجرا می کند .

تا کنون همه ی اعضا را به عنوان اعضأی عمومی درنظر می گرفتیم. اگر میل دارید که میزان دسترسی اعضا را محدود کنید باید کلاس را به عنوان خصوصی یا حفاظت شده تعریف کنید.

اعضای خصوصی

با معرفی یک عضو به عنوان عضو خصوصی ، شما دسترسی این عضو در کلاسی که معرفی می شود را محدود می کنید. نمی توان  به عضو خصوصی از کلاسهایی که  کلاس  تعریف شده در آن معرفی می شود اشاره کرد و دسترسی به آن خارج از کلاس امکان پذیر نیست.

با قرار دادن کلیدواژه ی private در مقابل عضو، می توانید آن عضو را خصوصی کنید.

class MyClass {‎

‎   private $car = “skoda”;‎

‎   $driver = “SRK”;‎

‎   function __construct($par) {‎

‎      // Statements here run every time‎

‎      // an instance of the class

‎      // is created. ‎

‎   }‎

‎   function myPublicFunction() {‎

‎      return(“I’m visible!”);‎

‎   }‎

‎   private function myPrivateFunction() {‎

‎      return(“I’m  not visible outside!”);‎

‎   }‎

‎}‎

هنگامی که my class  با استفاده از extends  توسط کلاس دیگری به ارث برده می شود،  myPublicFunction()  و $driver هر دو پدیدار می گردند.

کلاس در حال گسترش {extending class} هیچ آگاهی و دسترسی به myPrivateFunction  و $car ندارد،  وآن به این دلیل است که هر دو ی آن ها خصوصی اعلام شده اند.

اعضای محافظت شده

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

با قرار دادن کلیدواژه ی protected در مقابل عضو، می توانید آن عضو را محافظت شده کنید.

در زیر نسخه ی دیگری از Myclass را می بینید.

class MyClass {‎

‎   protected $car = “skoda”;‎

‎   $driver = “SRK”;‎

‎   function __construct($par) {‎

‎      // Statements here run every time‎

‎      // an instance of the class‎

‎      // is created. ‎

‎   }‎
‎   function myPublicFunction() {‎

‎      return(“I’m visible!”);‎
‎   }‎
‎   protected function myPrivateFunction() {‎

‎      return(“I’m  visible in child class!”);‎

‎   }‎

‎}‎

واسط ها {interface}

واسط یا رابط ها به منظور فراهم کردن اسم توابع {function name} های معمول و عادی برای مجریان {implementer}  تعریف می شوند. مجریان متفاوت می توانند بر اساس نیازهایشان آن رابط ها را اجرا کنند. می توانیم بگوییم، رابط ها حکم طرح یا ساختمان را دارند که توسط برنامه نویسان به مرحله ی اجرا در می آیند.

از PHP5 به بعد، شیوه ی معرفی رابط به صورت زیر می باشد.

interface Mail {‎

‎   public function sendMail();‎

‎}‎

و در صورتی که کلاس دیگری آن رابط را اجرا کرده باشد، این گونه خواهد بود.

class Report implements Mail {‎

‎   // sendMail() Definition goes here‎

‎}‎

ثابت ها {constant}

یک ثابت از جهتی مانند متغیر می باشد، به این مفهوم که مقدار {value} دارد، ولی از آن جهت که تغییر ناپذیر است بیشتر به تابع {function} شباهت دارد. به محض تعریف یک ثابت، آن ثابت به هیچ وجه تغییر نمی کند.

همین طور که در این نسخه ی MyClass مشاهده می کنید، تعریف یک ثابت بسیار آسان است.

class MyClass {‎

‎   const requiredMargin = 1. 7;‎

‎   function __construct($incomingValue) {‎

‎      // Statements here run every time‎

‎      // an instance of the class‎

‎      // is created. ‎

‎   }‎

‎}‎

در این کلاس requiredMargin یک ثابت است. با کلیدواژه const معرفی شده و تحت هیچ شرایطی هم قابل تغییر به هیچ چیز جز ۱٫ ۷ نیست. توجه داشته باشید که بر خلاف متغیرها، اسم ثابت ها {constant names}$ آغازین ندارند.

کلاس های انتزاعی {abstract classes}

کلاس انتزاعی را فقط می توان به ارث برد {inherit} و قابل نمونه سازی نیست. شما باید یک کلاس انتزاعی را با کلیدواژه ی abstract معرفی کنید به این صورت

هنگامی که  وراثت از یک کلاس انتزاعی صورت می پذیرد، تمام متُد هایی که در تعریف کلاس والد {parent class declaration}  با abstract  نشانه گذاری شده ه اند باید حتماً توسط  فرزند تعریف شوند، به علاوه، این متدها باید با همان مقدار پدیداری یا دید {visibility} معرفی شوند.

abstract class MyAbstractClass {‎

‎   abstract function myAbstractFunction() {‎

‎   }‎

‎}‎

توجه داشته باشید که تعاریف تابع {function definition} درون یک کلاس انتزاعی  باید بعد از کلیدواژه ی abstract قرار گیرند. داشتن تعریف تابع انتزاعی {abstract function definition} در یک کلاس غیر انتزاعی صحیح و قانونی نیست.

کلید واژه ی ایستا { static}

تعریف اعضای کلاس یا متدها به ایستا، دستیابی به آن ها را بدون نیاز به نمونه سازی کلاس ممکن می سازد. عضو ایستا تعریف شده را نمی توان با شی کلاس نمونه سازی شده {instantiated class object} به آن دسترسی پیدا کرد. (در صورتی که یک متد ایستا می تواند.)

مثال زیر را امتحان کنید.

‎<?php‎

class Foo

‎{‎

‎    public static $my_static = ‘foo’;‎

‎ ‎

‎    public function staticValue() {‎

‎        return self::$my_static;‎

‎    }‎

‎}‎

print Foo::$my_static .  “\n”;‎

‎$foo = new Foo();‎

print $foo->staticValue() .  “\n”;‎

کلید واژه ی نهایی

PHP کلید واژه ی نهایی را معرفی می کند، که از فرایند لغو شدن متدها توسط کلاس فرزند که با قرار دادن final پیش از تعریف {definition} انجام می پذیرد،  جلوگیری می کند. اگر خود کلاس final معرفی شود، دیگر نمی توان آن را بسط داد.

مثال زیر به نتیجه ی  خطا ی مهلک {fatal error} ختم می شود.

Cannot override final method BaseClass::moreTesting()

‎<?php‎

class BaseClass {‎

‎   public function test() {‎

‎       echo “BaseClass::test() called

‎”;‎

‎   }‎

‎‎

‎   final public function moreTesting() {‎

‎       echo “BaseClass::moreTesting() called

‎”;‎

‎   }‎

‎}‎

class ChildClass extends BaseClass {‎

‎   public function moreTesting() {‎

‎       echo “ChildClass::moreTesting() called

‎”;‎

‎   }‎

‎}‎

‎?>‎

فراخوانی سازنده ی والد {parent constructor}

به جای این که یک سازنده ی کاملاً جدید برای زیرکلاس {subclass} بسازید، اجازه دهید با صریحاً فراخواندن سازنده ی والد آن را بنویسیم و هر کار دیگری که برای نمونه سازی زیرکلاس الزامی است انجام دهیم. مثال ساده ی زیر را در نظر بگیرید.

class Name

‎{‎
‎   var $_firstName;‎

‎   var $_lastName;‎

‎   function Name($first_name، ‏‎ $last_name)‎

‎   {‎
‎     $this->_firstName = $first_name;‎

‎     $this->_lastName = $last_name;‎

‎   }‎
‎   function toString() {‎
‎     return($this->_lastName . “‎، ‏‎ ” . $this->_firstName);‎

‎   }‎
‎}‎

class NameSub1 extends Name
{‎
‎   var $_middleInitial;‎

‎   function NameSub1($first_name، ‏‎ $middle_initial‎، ‏‎ $last_name) {‎

‎       Name::Name($first_name، ‏‎ $last_name);‎

‎       $this->_middleInitial = $middle_initial;‎

‎   }‎

‎   function toString() {‎
‎       return(Name::toString() .  ” ” .  $this->_middleInitial);‎

‎   }‎

‎}‎

در این مثال، یک {name} (اسم) کلاس والد داریم که دارای دو سازنده ای دو-آرگومانه هست و یک زیر کلاس (NameSub1) که یک سازنده ی سه-آرگومانه دارد. سازنده ی NameSub1  با صریحاً فراخواندن سازنده ی والد با کمک :: syntax (با ارسال یا واگذاری دو تا از آرگومان های خود) و انتخاب یک فیلد جدید عمل کرده و کار خود را انجام می دهد. به طور مشابه، NameSub1 تابع غیرسارنده ی toString() خود را از نظر تابع والد ای که لغو می کند تعریف می کند.

توجه

یک سازنده را می توان با همان اسمی که یک کلاس تعریف می شود معرفی کرد. در مثال بالا نمومه ی تعریف شده ی آن را مشاهده می کنید.