classTransaction {privateconst STATUS_PAID = '1';publicconst STATUS_PENDING = '2';publicfunction__construct(){echoTransaction::STATUS_PENDING;echoself::STATUS_PENDING; // self - текущий класс или вызываемый }}/******///где то в другом месте кодаTransaction::STATUS_PENDING; // 1, вполне допустимо// :: - оператор разрешения области видимости// позволяет обращаться к константе, статическому свойству или статическому методу класса или одному из его родителей.// если у нас уже есть экземпляр класса$transaction = newTransaction();$transaction::STATUS_PENDING; // 1, вполне себе вариант$transaction::class; // выведет полное имя класса с namespace
Статические свойства и методы
// подходит для ситуаций где нам не нужен экземпляр класса, к примеру// Format::dateToFormat(); но считается "такой себе" практикой// либо для закрытия доступа к $this classTransaction {publicstaticint$count = 0; // доступ как к константе. не привязаны к экземпляру// работает глобальноpublicfloat$amount = 0;__construct(){self::$count++; // будет работать при создании нового экземпляра и сохранять значение }publicstaticfunctiongetCount(): int {echo$this->amount; // за это бан, в статических методах нельзя привязываться к экземплярамreturnself::$count; }}/****/echoTransaction::$count; // только для статических свойствechoTransaction::$amount; // за это бан, не статическое свойство же
Инкапсуляция
//объединение данных и методов в один объект, например в класс//скрывая его части, защищая его целостность//гарантирует что объект управляет своим состоянием и никто не сможет его изменить//без соответствующего разрешения//get и set не особо к инкапсуляции относится, да и вообще фигня// самое важное, не давать возможностей менять то что должно быть закрытым и стабильным
Наследование
// наследуются public, protected, methods, properties, constants// extend - скорее расширение класса чем "наследование"// private не наследуется и не может быть переопределено// нельзя понижать видимость, к примеру public -> private / за это банclassToaster {publicarray$slices = [];publicint$size = 2;publicfunctionaddSlice(string$slice): void {if (count($this->slices) < $this->size){$this->slices[] = $slice; } }publicfunctiontoast(){foreach($this->slices as $i => $slice){echo ($i + 1) .': Toasting '.$slice. PHP_OEL; } }}classToasterProextendsToaster { // расширение класса Toaster //ToasterPro наследует все что есть в Toaster (открытая часть)publicint$size = 4;publicfunctiontoastBagel(){foreach($this->slices as $i => $slice){echo ($i + 1) .': Toasting '.$slice.' with bagels option'. PHP_OEL; } }}/****/$toaster = newToaster();$toaster->addSlice('bread');$toaster->addSlice('bread');$toaster->addSlice('bread');$toaster->toast();/* 1: Toasting bread2: Toasting breadвлезло только 2, вышли за лимит *//****/$toaster = newToasterPro();$toaster->addSlice('bread');$toaster->addSlice('bread');$toaster->addSlice('bread');$toaster->toastBagel();/*1: Toasting bread with bagels option2: Toasting bread with bagels option3: Toasting bread with bagels option*/
__construct в наследовании
classToast {protectedarray$slices;protectedint$size;publicfunction__construct(){ // к слову можно и без него$this->slices = [];$this->size = 2; }}classToasterPro {publicfunction__construct(){parent::__construct(); //и только так//иначе бан, т.к. родительский __construct не вызывается//при создании экземпляра потомка// и по этому свойства родителя могут быть недоступны$this->size = 4; }//метод должен полностью совпадать с родительским, и типы и атрибуты и возвращаемое значениеpublicfunctionaddSlice(){parent::addSlice(); // на случаей если мы переопределяем родительский метод// и при этом хоти чтобы он все же сработал// без parent будет работать только этот метод }}
Ограничения наследования
finalclassToaster{// этот класс не может быть расширен и extends Toaster в банfinalpublicfunctionaddSlice(){// этот метод нельзя переопределять в дочерних классах }}
Абстрактные классы и методы
//как понятие, ближе к инкапсуляции//основа: внутренние детали реализации не важны для реализации задачи// и не должны быть видны в том же месте//иными словами следует делать так чтобы внутренная реализация методов не мешала их использованию//и изменения внутренней работы не сказывались на внешнем коде// абстрактные классы нельзя создать, можно только наследовать// не должны содержать реализацию методов (знает что сделать но не знает как)namespaceApp;abstractclassField {publicfunction__construct(protectedstring$name){ }abstractpublicfunctionrender(): string; // только сигнатура, без реализации//теперь все наследуемые классы должны реализовывать метод render}classTextextendsField {publicfunctionrender(): string {return<<<HTML<inputtype="text"name="{$this->name}"/>HTML; }}abstractclassBooleanextendsField {//в наследуемых абстрактных классах не обязательно}classCheckboxextendsBoolean {publicfunctionrender(): string {return<<<HTML<inputtype="checkbox"name="{$this->name}"/>HTML; }}classRadioextendsBoolean {publicfunctionrender(): string {return<<<HTML<inputtype="radio"name="{$this->name}"/>HTML; }}// вот теперь поабстрагируем$fields = [// new \App\Field('baseField'), За это бан, он жеж абстрактныйnew \App\Text('textField'),// new \App\Boolean('booleanField'), так ведь и за это банnew \App\Checkbox('checkboxField'),new \App\Radio('radioField'),];foreach($fields as $field) {echo$field->render()."<br />"; // }
Полиморфизм
// душный вариант//это способность обьекта использовать методы производного класса, который не существует на момент создания базового. //подробнее в следующем разделе