2012-10-16 14 views
0

代碼示例是我正在處理的一個簡單示例。 我有2個類在PHP中。這裏php OOP找出方法參數是否是子類中的方法

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」。 「包裝」類必須採用此形式。

...如果我有以下方法通話:

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

...我想有以下輸出:BA1ABABaaBAbbbABAcccABA

是否有其他辦法嗎?

我也希望Wrap-Class能獨立工作(沒有Child)......這就是爲什麼這些方法具有返回值。

但在子類中我想寫一個變量的返回值。

THX提前!

+1

'是否可以檢查「$ arg」是否是函數/方法?'在這種情況下,$ $ arg永遠不會是函數或方法。這是另一個方法調用的返回值。 – Dan

回答

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

老答案

爲了使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()只要需要被包裝就會被調用。

以上將生成正確的結果。

+0

應該返回$ this-> OUT。 parent :: wrapX($ arg);'有? 您的回答沒有幫助,因爲它不能解決問題。它只是以詳細的方式顯示發生了什麼... –

+0

@JohnDoeSmith從我的角度來看,(已知)問題的確切解決方案並不完全清楚,因爲我不知道爲什麼創建了「子」。我已經更新了我的答案,但我懷疑這也能解決它。 –

+0

@JohnDoeSmith改變了一些更多的東西,它產生正確輸出,但不知道該行爲是否確實是正確的:) –

1

我將此添加到我的最愛作爲一個有趣的難題來解決。

然後發現在我醒來後再次查看問題並沒有那麼複雜。 老實說,我不覺得,因爲技術上Child你應該使用子類在這一點上是沒有邏輯的Wrap類的孩子,它本質上似乎是想要存儲包裹的的輸出結果的人。

so ..這是我的修改,適用於您的原始界面。希望對你有好處;)。

它使神奇的方法一些非常神奇的用法。

<?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 

這是你在你原來的問題貼什麼。

+0

對不起... 1.「孩子」類是一個子類...我想在這裏找到的僅僅是這個類應該有的1個功能...... 2.你寫的很好,但它不適用於下面的調用在主方法: '$ X-> wrapB( \t $ X-> wrapA( '1') ); $ X-> wrapA( \t $ X-> wrapB( 'AA') \t。$ X-> wrapA( 'BBB') \t。$ X-> wrapB( \t \t $ X-> wrapA('cccc') \t) );'($ X就像代碼中的$ reader一樣) –

+0

@JohnDoeSmith但是..它輸出的內容正是您在原始問題中發佈的內容:x。實際上,作爲編輯,我注意到它沒有開始部分。哎呀!我通過做兩回聲欺騙。 – Anther

+0

你..這是作弊。但是,嘿..我不想在用法中使用** echo **,這就是爲什麼我在這裏發佈這個問題。如果我使用echo,我不需要在Child-class(或WrapReader)中進行任何修改..因爲所有的方法都是繼承的.. –