代码示例是我正在处理的一个简单示例。 我在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!答案 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
您在原始问题中发布了这个内容。