2009-05-07 6 views
0

wir haben ein Problem [cit.]PHP: ‚Dynamic‘ Rückruf von innen/außen eine Klasse

Ich brauche einen Rückruf dynamisch innerhalb einer Klasse zugeordnet wird, in der Basis eines variablen param: Mein Ziel ist es zu haben nur eine Klasse (und nicht eine Hauptklasse und viele Extender Unterklassen), und innerhalb dieser Klasse, wenn ein Wert X ist, dann muss die Funktion funcitonX verwendet werden, wenn Y die Funktion Y ist.

ich weiß, dass ich gut erklären kann nicht, ich hoffe, mein Beispiel tun:

class plzComplicateMyLife{ 
    public $vehicle; 
    public $kindVehicle; 
    public $dynamicFunction; 
    public function __construct($vehicle, $kindVehicle){ 
    $this->kindVehicle = $kindVehicle; 
    $this->vehicle = $vehicle; 
    switch($kindVehicle){ 
     case 'cycle': 
      $this->dynamicFunction = "isACycle"; 
      break; 
     case 'car': 
      $this->dynamicFunction = "isACar"; 
      break; 
    } 
    //here come the problem, i need to call the callback store in dynamicFunction. 
    //i tried: 
    //call_user_func($this->$this->dinamicFunction, $this->vehicle); 
    //error: Catchable fatal error: Object of class plzComplicateMyLife could not be converted to string in [...] 
    //call_user_func("plzComplicateMyLife::".$this->dynamicFunction); 
    //Warning: call_user_func(plzComplicateMyLife::isACar) [function.call-user-func]: First argument is expected to be a valid callback in [...] 
    //$this->dynamicFunction(); 
    //Fatal error: Call to undefined method plzComplicateMyLife::dynamicFunction() in [...] 
    //so, how can i do that? 
    } 
    public function isACycle($vehicle){ 
     echo 'im a cycle, model: '.$vehicle.'<br />'; 
    } 
    public function isACar($vehicle){ 
     echo 'im a car, model: '.$vehicle.'<br />'; 
    } 
    //i know this has no sense, in this example at least. 
    public function printKind(){ 
     //call_user_func($this->$this->dinamicFunction, $this->vehicle); 
     //call_user_func("plzComplicateMyLife::".$this->dynamicFunction); 
     //then? 
    } 
} 

$maserati = new plzComplicateMyLife('maserati4', 'car'); 

//then, maybe, outside the class i'll need to recover the callback: 

$maserati->printKind(); 

EDIT:

Als Rob sagte, würde Polymorphismus wirklich eine gute Lösung sein.

Aber das Problem ist, dass in diesem Fall ich wirklich muss die gleiche Erklärung für jede Instanz der Klasse haben, werden nur die Parameter zu ändern ... zB:

$maserati = new plzComplicateMyLife('maserati4', 'car'); 
$ducati = new plzComplicateMyLife('maserati4', 'cycle'); 
//is good 
//becose i cant have: 
$maserati = new plzComplicateMyLifeWithACar('maserati4'); 
$ducati = new plzComplicateMyLifeWithACycle('maserati4'); 

Antwort

1

Als Reaktion auf Ihre Bearbeitung, könnten Sie stattdessen etwas tun?

abstract class MethodOfTransport { 
    protected $model; 

    public function __construct($model) { 
     $this->model = $model; 
    } 

    abstract public function printKind(); 

    public static function create($model, $type) { 
     $object = new $type($model); 
     return $object; 
    } 
} 

class cycle extends MethodOfTransport { 
    public function printKind() { 
     echo 'im a cycle, model: '.$this->model.'<br />'; 
    } 
} 

class car extends MethodOfTransport { 
    public function printKind() { 
     echo 'im a car, model: '.$this->model.'<br />'; 
    } 
} 

$maserati = MethodOfTransport::create('maserati4', 'car'); 
$maserati->printKind(); 

$ducati = MethodOfTransport::create('maserati4', 'cycle'); 
$ducati->printKind(); 
+0

Yes'n sein Exacle, was ich tun werde! Danke, Kumpel! – Strae

+0

Ich habe es nicht versucht, aber ich falsch liegen mit der Aussage, wenn jede dieser Klassen in separaten Quelldateien definiert wäre, dann müsste die Basisklasse die erweiterten Klassendefinitionsdateien enthalten, während gleichzeitig die erweiterten Klassen müsste die Basisklasse enthalten? (Der einzige Grund, warum ich mich nicht sicher bin, ist die Verwendung von 'new $ type ($ model)'.) – grantwparks

+0

Die erweiterten Klassen müssten nur die Basisklasse enthalten, wenn sie nicht bereits enthalten wäre erweiterte Klassendateien, bevor sie instanziiert werden, das wäre alles was Sie tun müssen. Alternativ können Sie spl_autoload_register() betrachten –

1

In PHP können Sie verwenden angeben ein Verfahren Rückruf ein Array als Callback-Variable (see here), zum Beispiel mit:

array($object, $methodName); 

so könnten Sie tun dies

$callback = array($this, $this->dynamicFunction); 
call_user_func($callback, $this->vehicle); 
1

Er, warum nicht Sie wollen hier eine einfache Vererbungsstruktur verwenden? Wenn Sie ein unterschiedliches Verhalten in Abhängigkeit vom modellierten Objekt wünschen, dann ist dies die kanonische Beschreibung des Polymorphismus.

Wenn Sie mit Rückrufe in das gleiche Objekt wollen pflügen auf wirklich, müssen Sie dann eines von zwei Dingen tun:

  1. Drop the $vehicle Parameter von Ihrem Rückrufe, sie privat oder geschützt, und rufen sie in sie normalerweise, also

    call_user_func(array($this, 'isACycle'));

  2. markieren sie den Rückruf als statisch, machen sie privat oder geschützt, und in sie nennen wie folgt:

    call_user_func(array(__CLASS__, 'isACycle'), $this);

Innerhalb des nicht-statischen Rückrufs, greifen Sie auf die Eigenschaften des Objekts über $this in der normalen Art und Weise. Beachten Sie auch, dass ich vorschlage, den Rückruf als privat oder als geschützt zu markieren, um unnötige externe Anrufer zu vermeiden. Vermutlich möchten Sie nicht, dass sie für jeden Typ die falsche Methode ausführen.

+0

ich die Post nur mit der editierte, warum ich Polymorphismus verwenden kann nicht .. – Strae

2

Polymorphismus ist die Art und Weise hier zu gehen, aber für die Zukunft können Sie auch dies tun:

public function printKind() { 
    $this->{$this->dynamicFunction}($this->vehicle); 
}