Domanda

stavo lavorando su una classe astratta per risparmiare su qualche codice per un paio di classi. Queste classi sono tutte le fabbriche che si esemplificano attraverso chiamate statiche differenti. Potrei risparmiare un po 'di codice mettendo tutti quei metodi in una classe astratta.

Comunque, mi sono imbattuto in un in ritardo static binding problema ... dato che il nostro host web non sta usando 5.3 o versione successiva, non ho accesso ai get_called_class. Se ho

$class = __CLASS__;
return new $class();

nella classe astratta, __CLASS__ è il nome della classe astratta, quando io in realtà voglio utilizzare la classe chiamata.

Ho visto esempi di fabbriche astratti sul web dove le classi figlie hanno i propri metodi di istanza, e non si basano sul padre astratto per esso. Tuttavia, in questa situazione, l'unica ragione per la classe astratta è quello di salvare il codice, quindi se non posso farlo lì, il valore di essa diminuisce notevolmente.

C'è una soluzione in php <5.3? debug_backtrace()?


Modifica

Ho fatto un test e sembra debug_backtrace() non funziona! Credo che questo è il motivo per cui abbiamo bisogno vincolante ritardo statico .

<?

abstract class abstractFactory {
    public function create() {
            print_r(debug_backtrace());
            $class = __CLASS__;
            return new $class();
    }
}

class concreteFactory extends abstractFactory {}

$chimborazo = concreteFactory::create();

e il risultato:

$ php test.php
Array
(
    [0] => Array
        (
            [file] => /var/www/test.php
            [line] => 13
            [function] => create
            [class] => abstractFactory
            [type] => ::
            [args] => Array
                (
                )

        )

)

Fatal error: Cannot instantiate abstract class abstractFactory in /var/www/test.php on line 7
È stato utile?

Soluzione 3

Una volta modo per farlo è quello di sostituire i vari metodi di istanza, e passare il nome della classe direttamente:

<?

abstract class abstractFactory {

    public function create($class) {
        return new $class();
    }

    public function instantiate($class) {
        return new $class();
    }

}

class concreteFactory extends abstractFactory {

    public function create() {
        parent::create(__CLASS__);
    }

    public function instantiate() {
        parent::instantiate(__CLASS__);
    }
}


$chimborazo = concreteFactory::create();
$chimborazo = concreteFactory::instantiate();

Altri suggerimenti

L'unica soluzione che ho visto per questo comporta chiamare debug_backtrace per determinare il nome della classe del chiamante (s). Si tratta naturalmente di un hack gigante. Ho visto un po 'di codice che combina un backtrace con in realtà l'apertura del file di chiamare e analizzarlo per le cose capire. Bizzarro, roba orribile.

La mancanza di LSB sta per tornare e mordere in seguito. Aggiorna ora, anche se ciò significa che gli host di commutazione. Infatti, specialmente se significa commutazione host. 5.3 è stato fuori per un anno.

Ecco quello che ho usato fino a trasferirsi a 5,3:

if (!function_exists('get_called_class')) {

   /**
    * Implementation of get_called_class() for pre-5.3 PHP
    *
    * @return string
    */
   function get_called_class()
   {
      $bt = debug_backtrace();
      $lines = file($bt[1]['file']);
      preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
               $lines[$bt[1]['line']-1],
               $matches);
      return $matches[1];
   }
}

Questo consente di determinare in una funzione statica che nome della classe la funzione è stata invocata con. Si tratta di una soluzione che ha alcuni problemi di prestazioni, ma è l'unico che ho trovato avete. Se ci sono altri Sarei interessato a sapere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top