繁体   English   中英

PHP:类内部/外部的“动态”回调

[英]PHP: 'Dynamic' callback from inside/outside a class

我们有一个问题[cit。]

我需要在一个类内以变量参数为基础动态分配一个回调:我的目标是只有一个类(而不是主类和许多扩展子类),如果值是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');

多态性是解决问题的方法,但为将来参考,您也可以这样做:

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

在PHP中,您可以使用数组作为回调变量来指定方法回调( 请参见此处 ),例如:

array( $object, $methodName );

所以你可以这样做

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

嗯,为什么不在这里使用简单的继承结构? 如果您希望根据建模对象的不同而采取不同的行为,那么这就是多态的典型描述。

如果您确实确实想对同一个对象使用回调,那么您将需要执行以下两项操作之一:

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

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

  2. 将回调标记为静态,将其设为私有或受保护,然后按如下所示对其进行调用:

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

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

根据您的修改,您是否可以做类似的事情?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM