Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Класс, реализующий примеси в PHP

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: (псевдо)множественное наследование для версии >=5.4
EuGen Администратор
Отправлено: 27 Марта, 2012 - 14:55:09
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Обсуждалось в теме:
http://forum.php.su/topic.php?fo...2&topic=1661
- вопрос об осуществлении множественного наследования в PHP.
Представляю вашему вниманию класс Inheritance, который позволяет наследовать от произвольных классов без их модификации, а так же сохраняющий области видимости при вызове методов.
PHP:
скопировать код в буфер обмена
  1. class Exception_Callback_Absent extends Exception
  2. {
  3.     function __construct()
  4.     {
  5.         parent::__construct();
  6.     }
  7. }
  8.  
  9. class Exception_Callback_Deny extends Exception
  10. {
  11.     function __construct()
  12.     {
  13.         parent::__construct();
  14.     }
  15. }
  16.  
  17. class Inheritance
  18. {
  19.     protected $_rgInheritance=array();
  20.     protected function createInheritance($rParent, $bAllowInstances=false)
  21.     {
  22.         $bReject=false;
  23.         if(get_class($this)!=get_class($rParent))
  24.         {
  25.             foreach($this->_rgInheritance as $rClass)
  26.             {
  27.                 if(get_class($rClass)==get_class($rParent))
  28.                 {
  29.                     $bReject=true;
  30.                     break;
  31.                 }
  32.             }
  33.         }
  34.         else
  35.         {
  36.             $bReject=true;
  37.         }
  38.         if($bAllowInstances || !$bReject)
  39.         {
  40.             $this->_rgInheritance[]=$rParent;
  41.         }
  42.     }
  43.     public function __call($sMethod, $rgParameters)
  44.     {
  45.         $fnBind = function($sMethod, $rgParameters)
  46.         {            
  47.             if(method_exists($this, $sMethod))
  48.             {
  49.                 $rReflect = new ReflectionMethod($this, $sMethod);
  50.                 if($rReflect->isPrivate())
  51.                 {
  52.                     throw new Exception_Callback_Deny();
  53.                 }
  54.                 return $this->$sMethod($rgParams);
  55.             }
  56.             else
  57.             {
  58.                 throw new Exception_Callback_Absent();
  59.             }
  60.         };
  61.         $bExecuted=false;
  62.         foreach($this->_rgInheritance as $rParent)
  63.         {
  64.             try
  65.             {
  66.                 $fnBind = $fnBind->bindTo($rParent, $rParent);
  67.                 $fnBind($sMethod, $rgParameters);
  68.                 $bExecuted=true;
  69.                 break;
  70.             }
  71.             catch(Exception_Callback_Deny $e)
  72.             {
  73.                 throw $e;
  74.             }
  75.             catch(Exception_Callback_Absent $e)
  76.             {
  77.                 continue;
  78.             }
  79.         }
  80.         if(!$bExecuted)
  81.         {
  82.             throw new Exception_Callback_Absent();
  83.         }
  84.     }
  85. }

Если предположить, что у нас есть:
PHP:
скопировать код в буфер обмена
  1. class Foo
  2. {
  3.    public function doFoo()
  4.    {
  5.       echo('called doFoo()'.PHP_EOL);
  6.    }
  7.  
  8.    protected function protectedFoo()
  9.    {
  10.       echo('called protectedFoo()'.PHP_EOL);
  11.    }
  12. }
  13.  
  14. class Bar
  15. {
  16.    public function doBar()
  17.    {
  18.       echo('called doBar()'.PHP_EOL);
  19.    }
  20.  
  21.    private function privateBar()
  22.    {
  23.       echo('called privateBar()'.PHP_EOL);
  24.    }
  25. }

То можно создать несложный пример использования:
PHP:
скопировать код в буфер обмена
  1. class FooBar extends Inheritance
  2. {
  3.    public function __construct()
  4.    {
  5.       $this->createInheritance(new Foo);
  6.       $this->createInheritance(new Bar);
  7.    }
  8. }
  9.  
  10. $rTest = new FooBar();
  11. $rTest->doFoo();
  12. $rTest->doBar();
  13. $rTest->protectedFoo();
  14. $rTest->privateBar();
  15. $rTest->notExists();

(сохранил в "Пользовательских функциях", чтобы легче было в дальнейшем отыскать).


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DeepVarvar Супермодератор
Отправлено: 28 Июня, 2012 - 09:41:09
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




EuGen, а в строке 82 случаем не UNCAUGHT Exception ? Если нет, то почему? Я не нашел обертки try в данном контексте.
 
 Top
EuGen Администратор
Отправлено: 28 Июня, 2012 - 09:51:36
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




DeepVarvar
В случае, если была сделана попытка вызвать несуществующий метод, произойдет исключение, обрабатывать которое оставлено на усмотрение пользователя данного класса. Класс будет искать первого псевдородителя, у которого существует вызываемый метод, но если не найдет ни одного, то произойдет вызов исключения. Сделано это по той причине, что неясно, __call какого из классов-псевдородителей вызывать в этом случае, поэтому и оставлено в таком виде.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DeepVarvar Супермодератор
Отправлено: 29 Июня, 2012 - 00:14:12
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




А, вот теперь понятно - с умыслом и про запас.
 
 Top
DlTA
Отправлено: 29 Июня, 2012 - 17:11:53
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




а мне вот интересно а это действительно настолько больная проблема, отсутствие множественного наследования?
 
 Top
EuGen Администратор
Отправлено: 29 Июня, 2012 - 17:30:17
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




DlTA
Ну, класс выше был написан исключительно из академического интереса, так как с появлением php 5.4 и traits (примесей) в нем всякого рода реализации множественного наследования уже не актуальны.
Само множественное наследование, строго говоря, не является необходимым приемом, так как любая система может быть спроектирована без его использования. Однако иногда оно может быть полезным и изящным решением некоторых проблем.
В моей практике не было случая, когда была большая нужда в такого рода построениях, так что, думаю, то, что множественного наследования нет в php - не большая беда.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Crate
Отправлено: 29 Июня, 2012 - 17:33:57
Post Id



Посетитель


Покинул форум
Сообщений всего: 312
Дата рег-ции: Янв. 2012  


Помог: 4 раз(а)




EuGen
А почему разрабы PHP не добавили такой возможности в сам язык? Просто очень интересно.
 
 Top
DeepVarvar Супермодератор
Отправлено: 29 Июня, 2012 - 17:52:36
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




Ну например для ACL с перекрестными правами ролей.
Хотя я не юзаю это, во всяком случае пока.
Как только понадобится - буду использовать.
 
 Top
caballero
Отправлено: 29 Июня, 2012 - 18:04:51
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




Crate пишет:
А почему разрабы PHP не добавили такой возможности в сам язык? Просто очень интересно.

потому что это сильно осложнит написание компилятора.


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
EuGen Администратор
Отправлено: 29 Июня, 2012 - 18:34:58
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Что ж, настоящего компилятора никто и не писал, но тем не менее - нет такой нужды. Без множественного наследования можно обойтись и в примере DeepVarvar - ну да это не так важно. И все же я не могу ответить однозначно на вопрос
Crate пишет:
А почему разрабы PHP не добавили такой возможности в сам язык? Просто очень интересно.

- ведь я не являюсь разработчиком PHP.
Однако я не удивлюсь, если в следующих версиях это будет сделано (взять хотя бы реализацию тех же traits - вещь полезная но явно не необходимая).


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
caballero
Отправлено: 29 Июня, 2012 - 18:59:28
Post Id


Активный участник


Покинул форум
Сообщений всего: 5998
Дата рег-ции: Сент. 2011  
Откуда: Харьков


Помог: 126 раз(а)




Цитата:
Однако я не удивлюсь, если в следующих версиях это будет сделано

надеюсь что не будет иначе PHP превратится в неповоротливого монстра. Если такие языки как java и C# обходятся без множественного наследования то PHP и подавно обойдется.
Те же трейты я лично даже не представляю куда можно приткнуть так чтобы по уму а не лишь бы было. Замыкания тоже сделаны через заднее место.

Кстати раз уж в твоем примере используется интроспекция (рефлексия в смысле) то можно сделать более элегантное решение - указывать типа наследуемые классы в типа аннотациях


-----
Бесплатная система складского учета с открытым кодом https://zippy[dot]com[dot]ua/zstore
 
 Top
DeepVarvar Супермодератор
Отправлено: 29 Июня, 2012 - 19:12:43
Post Id



Активный участник


Покинул форум
Сообщений всего: 10377
Дата рег-ции: Дек. 2008  
Откуда: Альфа Центавра


Помог: 353 раз(а)




EuGen пишет:
Без множественного наследования можно обойтись и в примере DeepVarvar
Я именно так и обхожусь - без )))
Да, верно, все это просто еще один путь решения задачи по структуре приложения.
 
 Top
Stierus Супермодератор
Отправлено: 11 Июля, 2012 - 09:03:33
Post Id



Рекордсмен по количеству сообщений за 7 дней


Покинул форум
Сообщений всего: 2132
Дата рег-ции: Дек. 2008  
Откуда: Москваль


Помог: 52 раз(а)




Жень, ты б написал про паттерн decorator, все такое Улыбка

Насчет traits - это великое зло, не хотел бы я получить в наследство проект, написанный с их спользованием. Сами разработчики говорят, что это довольно сомнительное удовольствие, дебажить приложение с использованием трэйтов, что при их использовании невозможно отслеживать баги этих трейтов (в пыхе нет возможности понять, юзает класс тот или иной трейт или нет - а значит, используя метод, описаный в трейте из объекта - мы можем лишь надеятся, что он там есть Улыбка) На данный момент это один из самых вероятных источников огромного количества плавающих багов, я не вижу серьезных причин их использования.

Множественное наследование вообще ломает концепцию ООП и так же вызывает огромные сомнения по полезности Улыбка

ps
Я читал, что ты это делал из академического интереса, это я для новичков, которые задумываются над использованием подобных "хаков"
 
My status
 Top
EuGen Администратор
Отправлено: 11 Июля, 2012 - 09:16:59
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Stierus пишет:
Я читал, что ты это делал из академического интереса

Ну конечно. Практическая "ценность" этого кода - это посмотреть на использование Reflection плюс bindTo. Наверное, и все. Ну, может, показать "иллюзию" множественного наследования (хотя, какое же это наследование - если мы оперируем объектами, а не классами)
Насчет декоратора - посчитал, что это описание здесь не требуется.
Про traits - да, согласен. Использую php 5.4 отнюдь не из-за них, и, если честно, не возникло такой ситуации, где я бы не мог без них обойтись, при этом сохраняя стройность архитектуры и кода.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Stierus Супермодератор
Отправлено: 11 Июля, 2012 - 09:43:58
Post Id



Рекордсмен по количеству сообщений за 7 дней


Покинул форум
Сообщений всего: 2132
Дата рег-ции: Дек. 2008  
Откуда: Москваль


Помог: 52 раз(а)




zzz002, не впадлу было региться что бы гадость написать? Улыбка
 
My status
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Пользовательские функции »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB