PHP:来自课堂内外的'动态'回调

时间:2009-05-07 14:54:55

标签: php class callback

我们遇到了问题[cit。]

我需要在一个变量param的基础上动态地在一个类中分配一个回调:我的目标是让只有一个类(而不是一个主类和许多扩展子类),如果值为X,则在此类中,则必须使用funcitonX,如果为Y,则为functionY。

我知道我无法解释清楚,我希望我的榜样能够做到:

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

修改

Rob说,多态性确实是一个很好的解决方案。

但问题是,在这种情况下,我真的必须对每个类实例都有相同的声明,只更改参数......例如:

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

4 个答案:

答案 0 :(得分:2)

多态性是这里的方法,但为了将来参考,您也可以这样做:

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

答案 1 :(得分:1)

在PHP中,您可以使用数组作为回调变量(see here)来指定方法回调,例如:

array( $object, $methodName );

所以你可以这样做

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

答案 2 :(得分:1)

呃,为什么你想在这里使用简单的继承结构?如果你想根据建模的对象想要不同的行为,那么这就是多态的规范描述。

如果你确实想要将回调放到同一个对象中,那么你需要做两件事之一:

  1. 从您的回调中删除$vehicle参数,将其设为私有或受保护,并正常调用它们,即

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

  2. 将回调标记为静态,将其设为私有或受保护,并按如下方式调用它们:

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

  3. 在非静态回调中,以正常方式通过$this访问对象的属性。另请注意,我建议将回调标记为私有或受保护,以防止不必要的外部呼叫者;大概,你不希望他们为每种类型执行错误的方法。

答案 3 :(得分: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();