Інкапсуляція в обєктно-орієнтованому програмуванні на PHP

56

Від автора: досі ми з Вами, при створенні методів і властивостей, оголошували їх як public, то є абсолютно відкритими, що не зовсім добре. Тому в даній статті ми розглянемо два специфікатори доступу, а також вивчимо останній основний принцип, який був пропущений, під назвою — інкапсуляція в ООП на PHP.

Отже, хотів би нагадати, що елементи класу, можуть бути оголошені, як:

public – відкриті, або спільні;

protected – захищені;

private – закриті.

Доступ до загальнодоступних властивостей або методів відкритий з будь-якого контексту. Тобто, створивши об’єкт цікавить класу, Ви завжди можете вважати або змінити значення властивостей, оголошений як public, а так само звернутися до методів, у яких визначено даний спецификатор доступу.

title;

За великим рахунком ми з Вами це вже розглядали і не одноразово використовували на практиці, але повторення, як Ви знаєте, ні коли не буває зайвим.

До захищених елементів класу доступ ззовні, тобто з об’єкта, отримати не можна. Дозволяється звертатися до зазначених властивостей або методів з класу, в якому вони визначені, або з його підкласів.

title;
}
}
$index = new Page();
//призведе до помилки
echo $index->title;

Таким чином, якщо ми в попередньому прикладі, оголосимо властивість $title, використовуючи спецификатор доступу protected — спроба звернення до нього, через об’єкт, негайно призведе до помилки. Але при цьому, ми знаємо, що можна звертатися до подібного властивості, з класу, в якому воно визначено, а значить, ніхто не забороняє визначити відкритий метод, який буде повертати значення цікавить властивості.

title;
}
}
$index = new Page();
echo $index->getTitle();

Точно також, можна визначити метод, який буде змінювати значення захищеного властивості.

title;
}
public function setTitle($title) {
$this->title = $title;
}
}
$index = new Page();
$index->setTitle(«New String»);
echo $index->getTitle();

Захищені властивості і методи, так само доступні і в класах спадкоємців.

class Page {
protected $title = ‘Index Page’;
}
class IndexPage extends Page {
public function getTitle() {
return $this->title;
}
public function setTitle($title) {
$this->title = $title;
}
}
$index = new Page();
$index->setTitle(«New String»);
echo $index->getTitle();

При цьому до закритих властивостей або методів можна отримати доступ, тільки з того класу, в якому вони визначені і не більше. Таким чином, якщо в останньому прикладі, в батьківському класі оголосити властивість $title, зі специфікатором доступу private – інтерпретатор PHP поверне помилку, бо, повторюся, з дочірнього класу можна звертатися до закритих властивостями.

Звичайно ж, виникає питання, навіщо все це потрібно? Дивіться, специфікатори доступу, або як їх ще називають, ключові слова визначають область видимості, дозволяють надавати доступ тільки до тих елементів класу, які необхідні для конкретного клієнта. Відповідно контроль доступу, завдяки яким можна заборонити доступ до певних елементів класу, допомагає уникнути не правильною, роботи програми в цілому.

Тепер давайте розглянемо наступний приклад. Припустимо, що розробляється інтернет магазин, а значить працювати необхідно з товарами, для яких визначається ціна, при цьому, як правило, механізм ціноутворення досить складний, але ми його спростимо і умовимося, що остаточна ціна товару, буде формуватися з деякого значення базової ціни, а так само з урахуванням ставки оподаткування. Тому в самому простому вигляді, створимо наступний клас.

class Stuff {
public $nalog;
public $price;
public function setNalog($nalog) {
$this->nalog = $nalog;
}
public function getPriceTovar() {
return $this->price + $this->nalog;
}
}

Даний клас це як би основа, яка була створена, одним певним людиною і далі використовуючи його, інші члени команди будуть формувати функціонал майбутнього додатки. При цьому клас визначає метод getPriceTovar(), як доступ до остаточної ціни товару. Відповідно, що б отримати вищезазначену ціну необхідно зробити наступне:

$computer = new Stuff();
$computer->setNalog(100);
echo $computer->getPriceTovar();

Як Ви бачите, в принципі все дуже просто, є ціна, і є метод, який її формує. Але є невелика проблема, яка полягає в тому, що можна звернутися безпосередньо до властивості $price, в тому випадку якщо воно оголошено як відкрите. І в цьому випадку, податок не буде враховуватися для формування остаточної ціни, а значить, додаток буде працювати не коректно. Що б уникнути цього, необхідно оголосити властивість $price, зі специфікатором доступу private, тим самим доступ до властивості, буде дозволений тільки з методу getPriceTovar().

Але, в теж час, рівень видимості private, так само забороняє доступ до властивості з дочірніх класів, що призводить до того, що ми не зможемо створити підклас, і перевизначити метод getPriceTovar(), для дещо інший маніпуляції над властивістю $price. Наприклад, якщо потрібно для певної групи товарів, взагалі не використовувати податок при формуванні ціни, то ми могли б перевизначити метод getPriceTovar():

class Opt extends Stuff {
public function getPriceTovar() {
return $this->price;
}
}

Але даний код призведе до помилки, тому як властивість $price, закрито для всіх дочірніх класів.

А значить, оголошуючи дане властивість в батьківському класі, більш правильно використовувати спецификатор доступу protected і тим самим надати доступ до нього дочірнім класів.

З цього випливає невелика рекомендація щодо проектування структури класу. Спочатку визначте всі властивості і методи як закриті, а далі по мірі необхідності написання коду і ослабляйте обмеження. Краще зайвий раз закрити елемент класу, ніж помилково надати більший рівень видимості, ніж це необхідно.

Тепер ми з Вами плавно підійшли до останньому ключовому поняттю, під назвою — інкапсуляція.

В об’єктно-орієнтованому програмуванні на PHP инкапсуляцией називають властивість класів приховувати власну реалізацію. І, по суті, в найпростішому вигляді, ми з Вами тільки що инкапсулировали дані, використовуючи специфікатори доступу protected і private і тим самим закривали, або краще сказати приховували властивість $price від клієнтського коду. Тобто, при цьому задається якийсь інтерфейс доступу до даних і за великим рахунком, знаючи його, нам абсолютно все одно як влаштований конкретний клас, так як ми знаємо які методи в нашому розпорядженні і як їх слід використовувати, тим самим запобігається некоректна робота з даними класу.

При цьому поліморфізм, передбачає і реалізує кілька іншу інкапсуляцію в об’єктно-орієнтованому програмуванні на PHP і означає, що, розміщуючи різні реалізації певного інтерфейсу, Ви приховуєте працює на його основі-код. Таким чином, можна створювати нові класи, або редагувати існуючі і це не призведе до помилок. Значення має тільки інтерфейс, а не конкретний механізм який працює на його основі.

На цьому дана стаття завершена. Всього Вам доброго і вдалого кодування!!!