2011-01-13 17 views
5

¿Hay alguna forma de definir una clase para que se extienda otra clase solo si esa otra clase está disponible?Clase dinámica extender

+4

Esto no tiene mucho sentido desde una perspectiva arquitectónica, ya sea que necesite extender una clase o no. ¿Qué estás intentando lograr? (Puede haber una manera más fácil.) –

+4

No debería haber ninguna razón para crear clases dinámicamente, debería tener un sistema sólido que nunca debería requerir tal cosa. a menos que se indique lo contrario, podría haber un enfoque más simple para su objetivo. – RobertPitt

+0

RobertPitt es 100% correcto. Me gustaría replantear el problema porque parece que hay un error mayor en la estructura que debería analizarse primero. –

Respuesta

8

no hay nada que le permitirá hacer

class Foo extendsIfExist Bar 

Pero se puede monkeypatch Foo con runkit 's

Ejemplo de PHP Manual:

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

class myChild { 
} 

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

La extensión runkit está disponible desde PECL. Sin embargo, se desaconseja su uso porque necesitarlo casi siempre es un indicador de un diseño defectuoso.


responsabilidad: yo sólo estoy asumiendo algo como el siguiente ejemplo es la razón por la que está pidiendo a su pregunta. Haga caso omiso de esa parte de la respuesta si no es así.

Si necesita cierta funcionalidad condicionalmente en tiempo de ejecución, considere agregar la clase de la que desea extender, p. Ej. probar algo en la línea de

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); 
     } 
    } 
} 

En el ejemplo anterior, la funcionalidad que queremos es log(). Entonces, en lugar de detectar si una clase de registrador está disponible y luego asignar esta funcionalidad a nuestra clase Foo, le pedimos que requiera esta funcionalidad agregando una interfaz Registrable. Si existe una clase Logger, la instanciamos y agregamos en Foo. Si no existe, aún podemos llamar al registro pero no hará nada. Esto es mucho más solid.

+0

Solución para proporcionar "extender si existe" sin usar eval: http://stackoverflow.com/a/9898049/441739 –

1

¿Lo dice en serio?

<?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

No es bueno tampoco, pero es mejor que el enfoque 'eval()'! –

2

Esta es una respuesta y una extensión a la respuesta de Pekka.

primer lugar a Pekka, creo que el eval es totalmente erróneo, lo que está mal con

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

    } 
} 

que es también mi respuesta también.

2

encontrado un requisito similar hace poco, donde una clase en mi biblioteca necesario para extender dinámicamente desde ClassB (si existe), de lo contrario se extienden desde la Clase A.

Mi solución (mi código es el namespace, mismo concepto se aplica independientemente) :

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 ... 
} 

Uso de la solución anterior, la clase MyClass heredarán dinámicamente desde ClassB si existe, de lo contrario, se hereda de ClassA.

Esta solución evita usar eval, lo cual es una gran ventaja para mí.

Espero que esto ayude.

EDIT: Solo una nota, la notación @noinspection existe para que los IDEs como PHPStorm no informen errores con respecto a la clase inexistente.

4

Lo hice de esta manera.

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

Error si los archivos son externos 'Error fatal: las declaraciones de clase pueden no estar anidadas' –