2009-05-07 5 views
0

у нас есть проблемы [соч.]PHP: «Динамический» обратный вызов внутри/вне класса

Мне нужно назначить функцию обратного вызова динамически внутри класса, в основе переменной PARAM: моя цель состоит в том, чтобы иметь только один класс (а не основной класс и многоуровневый подкласс), и внутри этого класса, если значение X, тогда необходимо использовать funcitonX, если это Y, функция Y.

Я знаю, что я не могу объяснить, хорошо, я надеюсь, что мой пример будет делать:

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:

Как сказал Роб, полиморфизм был бы очень хорошим решением.

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

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

ответ

1

В ответ на ваши изменения, не могли бы вы вместо этого сделать что-то подобное?

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

Да, это то, что я сделаю! Спасибо, приятель! – Strae

+0

Я не пробовал, но я ошибаюсь, говоря, что если бы каждый из этих классов был определен в отдельных исходных файлах, тогда базовый класс должен был включать файлы расширенного класса, в то время как расширенные классы должен был бы включать базовый класс? (Единственная причина, по которой я не уверен, - это использование 'new $ type ($ model)'. – grantwparks

+0

Расширенные классы должны были бы включать только базовый класс, если он еще не включен. Базовый класс может нести ответственность за включение файлы расширенного класса до их создания, это все, что вам нужно сделать. В качестве альтернативы вы можете посмотреть spl_autoload_register() –

1

В PHP можно использовать указать метод обратного вызова с использованием массива в качестве переменной обратного вызова (see here), например:

array($object, $methodName); 

Таким образом, вы могли бы сделать это

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

Er, почему не Вы хотите использовать простую структуру наследования здесь? Если вы хотите различного поведения в зависимости от моделируемого объекта, то это в значительной степени каноническое описание полиморфизма.

Если вы действительно хотите, чтобы пахать на с обратными вызовами в том же объект, то вам нужно сделать одну из двух вещей:

  1. Снижения параметр $vehicle из ваших обратных вызовов, сделать их частными или защищена, и вызвать в них, как правило, т.е.

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

  2. Марк обратный вызов как статические, сделать их частными или защищенными, и вызвать в них следующим образом:

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

В нестатическом обратном вызове, доступ к свойствам объекта с помощью $this обычного способа. Также обратите внимание, что я предлагаю отмечать обратный вызов как закрытый или защищенный, чтобы предотвратить ненужные внешние вызывающие абоненты; предположительно, вы не хотите, чтобы они выполняли неправильный метод для каждого типа.

+0

Я просто редактировал пост с почему я не могу использовать полиморфизм .. – Strae

2

полиморфизм путь здесь, но для будущей ссылки Вы также можете сделать это:

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