2011-01-13 3 views
5

Есть ли способ определить класс, чтобы он расширил другой класс только в том случае, если этот класс доступен?Расширение динамического класса

+4

Это не имеет большого смысла с точки зрения архитектуры - либо вам необходимо расширить класс, либо нет. Чего вы пытаетесь достичь? (Возможно, будет более простой способ.) –

+4

Не должно быть причин для динамического создания классов, у вас должна быть прочная система, которая никогда не должна требовать такой вещи. если не указано выше, может быть более простой подход к вашей цели. – RobertPitt

+0

RobertPitt на 100% верный. Я бы переосмыслил проблему, потому что похоже, что в структуре есть большая ошибка, которая должна быть рассмотрена в первую очередь. –

ответ

8

Там нет ничего, что позволит вам сделать

class Foo extendsIfExist Bar 

Но вы можете monkeypatch Foo с runkit «s

Пример из PHP Manual:

class myParent { 
    function parentFunc() { 
    echo "Parent Function Output\n"; 
    } 
} 

class myChild { 
} 

runkit_class_adopt('myChild','myParent'); 
myChild::parentFunc(); 

Расширение Runkit доступно в PECL. Однако не рекомендуется использовать, так как он почти всегда является индикатором неправильной конструкции.


Отказ от ответственности: я только при условии, что-то вроде следующего примера является причиной того, почему вы задаете ваш вопрос. Не обращайте внимания на эту часть ответа, если это не так.

Если вам нужна определенная функциональность условно во время выполнения, подумайте об объединении класса, из которого вы хотите продлить действие, например. попробовать что-то вдоль линий

interface Loggable 
{ 
    public function log($message); 
} 
class Foo implements Loggable 
{ 
    protected $logger; 
    public function setLogger($logger) 
    { 
     $this->logger = $logger; 
    } 
    public function log($message) 
    { 
     if($this->logger !== NULL) { 
      return $this->logger->log($message); 
     } 
    } 
} 

В приведенном выше примере, функциональность мы хотим log(). Поэтому вместо того, чтобы определить, доступен ли класс журнала, а затем обезвредить эту функциональность в нашем классе Foo, мы говорим, что для этого требуется эта функциональность, добавив интерфейс Loggable. Если существует класс Logger, мы создаем и агрегируем его в Foo. Если он не существует, мы все равно можем вызвать журнал, но он ничего не сделает. Это намного больше solid.

+0

Решение для предоставления «продлить, если существует», без использования eval: http://stackoverflow.com/a/9898049/441739 –

1

Вы имеете в виду это?

<?php 

class Foo{ 
} 

if(class_exists('Foo')){ 
    class SubFoo extends Foo{ 
    } 
} 

if(class_exists('Bar')){ 
    class SubBar extends Bar{ 
    } 
} 

$a = new SubFoo; // OK 
$b = new SubBar; // Fatal error: Class 'SubBar' not found 
+0

Нехорошо, но лучше, чем подход 'eval()'! –

2

Это ответ и продолжение ответа Пекки.

Во-первых, в Пекка, я думаю, что Eval совершенно неправильно, что случилось с

if(class_exists("bar")) 
{ 
    class foo extends bar 
    { 

    } 
} 

, который также мой ответ, а также.

2

Встречающиеся аналогичное требование в последнее время, когда класс в моей библиотеке, необходимой для динамического расширения от ClassB (если есть), в противном случае простираться от класса А.

Мое решение (мой код в пространстве имен, то же самое понятие применяется независимо) :

namespace someNamespace; 

spl_autoload_register(function($class) { 
    if (strcasecmp($class, 'someNamespace\SomeFakeClass') === 0) { 
     if (class_exists('ClassB',false)) { 
      class_alias('ClassB', 'someNamespace\SomeFakeClass'); 
     } else { 
      class_alias('ClassA', 'someNamespace\SomeFakeClass'); 
     } 
    } 
}, true, true); 

/** @noinspection PhpUndefinedClassInspection */ 
/** @noinspection PhpUndefinedNamespaceInspection */ 
class MyClass extends \someNamespace\SomeFakeClass { 
    # ... real logic here ... 
} 

Использование вышеуказанного раствора, класс MyClass будет динамически наследоваться от ClassB, если существует, в противном случае он наследует от ClassA.

Это решение позволяет избежать использования eval, что является большим плюсом для меня.

Надеюсь, это поможет.

EDIT: Просто примечание, нотация @noinspection существует, так что IDE, такие как PHPStorm, не сообщают об ошибках относительно несуществующего класса.

4

Я сделал это на этом пути.

if (class_exists('parentClass') { 
    class _myClass extends parentClass {} 
} else { 
    class _myClass {} 
} 
class myClass extends _myClass 
{ 
... 
} 
+0

Ошибка, если файлы являются внешними 'Fatal error: объявления классов могут быть не вложенными' –

Смежные вопросы