PHP: içeriden / a sınıfın dışında 'Dinamik' geri çağırma

4 Cevap php

bir sorunumuz var [age.]

Ben bir değişken param tabanında, bir sınıf içinde dinamik bir geri atamanız gerekir: Amacım just one sınıfı (ve bir ana sınıf ve birçok genişletici alt sınıf), ve bu sınıf içinde var ise Y, functionY ise bir değeri, daha sonra funcitonX kullanılmalıdır, X'in.

Ben benim örnek yapmak umuyoruz, ben iyi anlatamıyorum biliyorum:

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:

Rob dediği gibi, polimorfizm gerçekten iyi bir çözüm olacaktır.

Ama sorun bu durumda, ben gerçekten must, örneğin sadece ... parametrelerini değiştirerek, her sınıf örneği için aynı beyanda sahip, yani:

$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 Cevap

Düzenlemenizi yanıt olarak, bunun yerine böyle bir şey yapamadı?

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

Polimorfizm buraya gitmek için ama ileride siz de bunu yapabilirsiniz yoludur:

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

PHP, örneğin (see here), bir geri çağırma değişken olarak bir dizi kullanarak bir yöntem geri arama belirtebilirsiniz kullanabilirsiniz:

array( $object, $methodName );

Peki bu yapabilirdi

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

Er, neden don't Burada basit bir kalıtım yapısını kullanmak ister misiniz? Eğer modellenen nesneye bağlı olarak farklı davranış istiyorsanız, o zaman hemen hemen polimorfizminin kurallı bir açıklama bulunuyor.

Eğer gerçekten aynı nesne içine geriçağırımlarının ile azimle istiyorsun, o zaman iki şeyden birini yapmak gerekir:

  1. Lütfen geri çağrıları gelen $vehicle parametresini Bırak, onları özel veya korumalı yapmak, ve, yani, normalde onlara çağrı

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

  2. Statik olarak geri arama işaretle, onları özel veya korumalı yapmak ve onlara şöyle içine çağırır:

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

Statik olmayan geri arama içinde, normal bir şekilde $this yoluyla nesnenin özelliklerine erişmek. Ben gereksiz dışında arayanlar önlemek için, özel veya korumalı olarak geri arama işaretleme önermek de unutmayın; muhtemelen, onları her tür için yanlış bir yöntem yürütme istemiyorum.