php OOP找出method参数是否是子类中的方法

时间:2012-10-16 09:35:19

标签: php class methods

代码示例是我正在处理的一个简单示例。 我在php中有2个类。

class Wrap {

    public function wrapA($arg){
        return 'A'.$arg.'A';
    }

    public function wrapB($arg){
        return 'B'.$arg.'B';
    }

}

class Child extends Wrap {

    public $OUT;

    public function wrapA($arg){
        $this->OUT .= parent::wrapA($arg);
    }

    public function wrapB($arg){
        $this->OUT .= parent::wrapB($arg);
    }

    public function __destruct(){
        echo $this->OUT;
    }

}

$X = new Child();

$X->wrapA(
    $X->wrapB('CC')
);

此处的输出为“ BCCBAA ”。但我试图实现的是“ ABCCBA ”。 “Wrap”类必须采用这种形式。

...如果我有以下方法调用:

  

$ X-> wrapB($ X-> wrapA('1'));

     

$ X-> wrapA($ X-> wrapB('aa')。$ X-> wrapA('bbb')。$ X-> wrapB(         $ X-> wrapA('cccc')));

...我希望得到以下输出: BA1ABABaaBAbbbABAcccABA

还有其他方法吗?

我还希望Wrap-Class单独工作(没有Child)......这就是方法具有返回值的原因。

但是在Child-Class中我想在变量中写入返回值。

提前THX!

2 个答案:

答案 0 :(得分:3)

那是因为$X->wrapB('CC')没有返回任何内容,并且在调用$X->wrapA()时被强制转换为空字符串,因此A无所事事。

但是,由于您将BCCB追加到$X->OUT,因此当您致电$X->wrapA()时,会将AA追加到BCCBAA,导致class Wrap { // The wrapping itself can be declared as a static method protected static function wrapWithChar($arg, $ch) { return $ch . $arg . $ch; } } class Child extends Wrap { protected $OUT; // we allow the internal state to be set upon construction public function __construct($s = '') { $this->OUT = $s; } // no arguments required here, this gets applied on the internal state public function wrapA() { $this->OUT = self::wrapWithChar($this->OUT, 'A'); // return instance to allow chaining return $this; } public function wrapB() { $this->OUT = self::wrapWithChar($this->OUT, 'B'); return $this; } public function __toString() { return $this->OUT; } public function __destruct(){ echo $this->OUT; } } // initialize with 'CC' $X = new Child('CC'); // wrap B around it; becomes 'BCCB' $X->wrapB(); // wrap A around that; becomes 'ABCCBA' $X->wrapA(); // example of chaining $Y = new Child('ZZ'); // wrap B then A around it; becomes 'ABZZBA' $Y->wrapB()->wrapA(); 。< / p>

再看一遍这个问题后,我觉得应该以另一种方式解决;这是值得考虑的事情:

Child

旧答案

要使Wrap显示为__toString()可以执行的操作,您可以使用instanceof魔术方法(使用class Child extends Wrap { public $OUT; public function wrapA($arg) { $this->OUT = parent::wrapA($arg); return $this; } public function wrapB($arg) { $this->OUT = parent::wrapB($arg); return $this; } public function __toString() { return $this->OUT; } public function __destruct(){ echo $this->OUT; } } 更明确,但也多一点工作):

wrapX()

每个__toString()方法现在返回实例本身,只要需要包装就会调用{{1}}。

以上将产生正确的结果。

答案 1 :(得分:1)

我将此添加到我的收藏夹作为一个有趣的难题来解决。

然后发现在我醒来并再次看到问题后并没有那么复杂。 老实说,我认为你不应该在这一点上使用子类,因为技术上Child在逻辑上不是Wrap类的子类,它本质上似乎是一个想要存储输出的人包裹的结果。

所以..这是我的修改,适用于您的原始界面。希望它对你有好处;)。

它使魔术方法非常神奇。

<?php
class Wrap {
    public function wrapA($arg){
        return 'A'.$arg.'A';
    }

    public function wrapB($arg){
        return 'B'.$arg.'B';
    }
}

class WrapReader{
    protected $wrapper;
    protected $currentResult;

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

    public function __call($method,$argument)
    {
        $argument = $argument[0];
        if(!method_exists($this->wrapper,$method))
            throw new MethodNotFoundException('Method: '.$method.'() does not exist in class: '.get_class($this->wrapper));
        $this->currentResult = $this->wrapper->$method($argument);
        return $this->currentResult;
    }

    public function __destruct(){
        echo $this;
    }

    public function __toString()
    {
        return $this->currentResult;
    }
}
class MethodNotFoundException extends Exception{}

用法:

$reader = new WrapReader(new Wrap());

echo $reader->wrapB( $reader->wrapA('1') ); 
echo $reader->wrapA( $reader->wrapB('aa') .$reader->wrapA('bbb') .$reader->wrapB( $reader->wrapA('cccc') ) );
echo '<br>';

Outputs BA1ABABaaBAbbbABAccccABA

您在原始问题中发布了这个内容。