главное слово здесь - "зло" =)Почему разработчики злоупотребляют наследованием?
Абсолютно верно, я читаю книгу. По ходу книги возникают вопросы. В параграфе "Механизмы повторного использования" объясняются плюсы/минусы наследования и композиции. Сам чаще использую наследование, авторы же говорятАвтор оригинала: Rammstein
Bermuda
А я думаю, что ты вырвал два слова из книги страниц эдак в *00, ибо в разных случаях нужно использовать разные методы/патены
и там жеЭто подводит нас ко второму правилу объектно-ориентированного проектирования: предпочитайте композицию наследованию класса.
Я осознаю, что это рекомендация, а не догма и каждая задача требует своего инструмента.Тем не менее, наш опыт показывает, что проектировщики злоупотребляют наследованием. Нередко дизайн мог бы стать лучше и проще, если бы автор больше полагался на композицию объектов.
Точно, не могли.И в "фундаментальном труде" не могли такого сказать однозначно.
++Я осознаю, что это рекомендация, а не догма и каждая задача требует своего инструмента
в точку попалПосле этого новичек домает что понял основную мысль ООП и начинает наследовать все что попадет под руку
Если оно не может существовать вне сущности, то композиция здесь не нужна. Но все дело в том, что многие сущности, которые некогда были выделены из некоторой другой, таки могут существовать (ака быть инкапсулированы) в других классах. В частности, данный случай. Что мешает передать кошелек некоторой организации, или выбросить его в трэш? Как дополнительный плюс такого подхода, если мы используем класс кошелька, мы можем без проблем менять его внутреннее устройство. И это никак не отобразится на механизме передачи кошелька от чела к организации или на процессе выбрасывания.Тогда я ввожу объект Account, который будет кошельком, аки счётом, но т.к. он не может существовать без чела - композиция тут идеальный вариант.
ИМХО, это именно тот случай. Кошелёк НИКОГДА не нужно будет отделён/передан от юзверя и их раздельное существование бессмысленно.Composition happens when one class instantiates another, the second class “dieing” when the first class dies.
In other words the first class controls the whole of the second class.
<?php
/*
* Класс для работы с точками доступа клиента (HotSpot)
*/
class Points {
public function __construct() {
//pass
}
/**
* Метод возвращает количество активных точек для указанного клиента
* @param <type> $clientID
* @return <array()>
*/
public function getCountActivePointsByClientID($clientID) {
$sql = "
select count(id) from points where client_id = {$clientID} and is_deleted = false
";
return $this->db->executeOne($sql);
}
}
/*
* Класс для работы с банковскими реквзитами клиента
*/
class ClientAccountingDetails {
public function __construct() {
//pass
}
/**
* Метод проверяет, удален ли ИНН клиента
* @param <int> $clientID
* @return <int>
*/
public function getActiveTaxIdentificationNumberByclientID($clientID) {
// тут проверка удален ли ИНН клиента из системы, если удален то такого клиента нельзя удалять с БД пока не удалить ИНН
$sql = "
........
";
$x = $this->db->execute($sql);
if($x == 1) { // не удален
return 1;
} else { // удален
return 0;
}
}
}
class Clients {
private $points;
private $clientAccountingDetails;
private $_clientID;
public function __construct($clientID) {
$this->_clientID = $clientID;
// Создвем наши кубики (коллекцию)
$this->points = new Points();
$this->clientAccountingDetails = new ClientAccountingDetails();
}
public function dropClient() {
// Если у клиента все еще еcть активные точки доступа то не удаляем
$countPoints = $this->points->getCountActivePointsByClientID($this->_clientID);
$activeTaxAccount = $this->clientAccountingDetails->getActiveTaxIdentificationNumberByclientID($this->_clientID);
if ( $countPoints > 0 and $activeTaxAccount == 1) {
// ... ничего не делаем и информируем пользователя о том что клиента нельзя удалять и прекращаем сценарий
} else {
// ... тут уже начинаетс удаление клиента и конец
}
}
}
/*
* Подтип класса Clients (Обычный клиент)
*/
class SampleClient extends Clients {
public function __construct($clientID) {
parent::__construct($clientID);
}
}
/*
* Подтип класса Clients (V.I.P клиент)
*/
class VipClient extends Clients {
public function __construct($clientID) {
parent::__construct($clientID);
}
}
/*
* Ну и наконец само использование этого кода
*/
...
$obj = new SampleClient($clientID);
$obj->dropClient();
...
//и тоже самое
...
$obj1 = new VipClient($clientID);
$obj->dropClient();
...