2011-01-13 13 views
5

Czy istnieje sposób zdefiniowania klasy, aby rozszerzyć inną klasę tylko wtedy, gdy ta druga klasa jest dostępna?Rozszerzenie klasy dynamicznej

+4

To nie ma większego sensu z architektonicznego punktu widzenia - musisz rozszerzyć klasę, albo nie. Co próbujesz osiągnąć? (Może być łatwiejszy sposób.) –

+4

Nie powinno być powodu do dynamicznego tworzenia klas, powinieneś mieć solidny system, który nigdy nie powinien wymagać czegoś takiego. chyba że, jak stwierdzono powyżej, może istnieć prostsze podejście do celu. – RobertPitt

+0

RobertPitt ma 100% poprawności. Ponownie zastanowiłbym się nad problemem, ponieważ wygląda na to, że istnieje większy błąd w strukturze, który należy najpierw zbadać. –

Odpowiedz

8
Nie

ma nic, co pozwoli Ci zrobić

class Foo extendsIfExist Bar 

Ale można monkeypatch Foo z runkit „s

Przykład z PHP Manual:

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

class myChild { 
} 

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

Rozszerzenie runkit jest dostępne z PECL. Jednakże, jego użycie jest zniechęcane, ponieważ jego użycie jest prawie zawsze wskaźnikiem wadliwego projektu.


Zastrzeżenie: Jestem zakładając, tylko coś jak w poniższym przykładzie jest powód, dlaczego pytasz pytanie. Zignoruj ​​tę część odpowiedzi, jeśli nie jest.

Jeśli w środowisku wykonawczym wymagana jest pewna funkcjonalność warunkowo, należy rozważyć agregację klasy, z której należy rozszerzyć, np. spróbować czegoś wzdłuż linii

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

W przykładzie powyżej, funkcjonalność chcemy to log(). Zamiast więc wykrywać, czy klasa rejestratorów jest dostępna, a następnie monkeypatchować tę funkcjonalność do naszej klasy Foo, informujemy, że wymaga tej funkcji poprzez dodanie interfejsu Loggable. Jeśli istnieje klasa Logger, tworzymy ją i agregujemy w Foo. Jeśli nie istnieje, możemy nadal wywoływać logi, ale nic nie zrobimy. To znacznie więcej niż solid.

+0

Rozwiązanie zapewniające "rozszerzenie jeśli istnieje" bez użycia eval: http://stackoverflow.com/a/9898049/441739 –

1

Masz na myśli to?

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

Niezły, ale lepszy od podejścia 'eval()'! –

2

Jest to odpowiedź i przedłużenie odpowiedzi Pekki.

pierwsze w Pekka, myślę, że eval jest całkowicie błędne, co jest nie tak z

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

    } 
} 

to również moja odpowiedź również.

2

napotkał podobny wymóg niedawno, gdzie klasa w mojej bibliotece potrzebne do dynamicznie rozciągają się od ClassB (jeśli istnieje), w przeciwnym razie rozciągać się od klasy A.

Moje rozwiązanie (mój kod jest przestrzeni nazw, samo pojęcie odnosi się niezależnie) :

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

Stosując powyższy roztwór, klasa MojaKlasa dynamicznie dziedziczyć ClassB jeśli występuje, poza dziedziczy ono od ClassA.

To rozwiązanie pozwala uniknąć używania eval, co jest dużym plusem dla mnie.

Mam nadzieję, że to pomoże.

EDIT: Tylko uwaga, notacja @noinspection istnieje tak że IDE takich jak PHPStorm nie będzie raportować błędy dotyczące nieistniejącej klasy.

4

Zrobiłem to w ten sposób.

+0

Błąd, jeśli pliki są zewnętrzne. Błąd krytyczny: deklaracje klasy nie mogą być zagnieżdżone. –

Powiązane problemy