2009-08-19 135 views
0

我想知道是否可以封裝一個類的方法,但是然後暴露它們在一個消費類。例如(JFTR,我知道這個代碼是錯誤的)封裝和繼承方法

class Consumer{ 
     public function __construct($obj){ 
      $this->obj = $obj; 
      } 

     public function doCommand(){ 
      $this->obj->command(); 
      } 
     } 

    class Consumed{ 
     //I would make the constructor private, but to save space... 
     public function __construct(){} 
     private function command(){ 
      echo "Executing command in the context of the Consumer"; 
      } 
     } 

    $consumer = new Consumer(new Consumed); 
    $consumer->doCommand(); 

    //just to reiterate, I know this throws an error 

最後,我希望能夠做的是不能在一個控制類的上下文外部直接引用的組件。

+0

你的意思是像C++中的朋友類的東西? http://en.wikipedia.org/wiki/Friend_class – VolkerK 2009-08-19 09:38:05

+0

如果你隱藏了私有方法中的功能,那麼你不能雙方都擁有它,那麼它就不能從外部調用。 如果以任何方式公開它(通過製作一個公共方法,然後調用私有方法),那麼每個人都可以調用您的私有方法。 – 2009-08-19 09:40:13

+0

上面的評論是關於PHP當然:)朋友類會工作,但PHP中沒有這樣的概念。 – 2009-08-19 09:44:57

回答

0

當然是可以的,只是讓那些方法protected,不private,並有ConsumedConsumer延伸。雖然我不確定這些好處。

+0

,以防止直接訪問他們的方法,並強制單點輸入。這是從設計的角度來看是不好的? – sunwukung 2009-08-19 12:15:52

+0

可能是。我的意思是,「消費」級別基本上是不可測試的。沒有公共接口的課程的目的是什麼?也許這是一個你並不需要那個課程的標誌。訪問限制不一定能保證良好的設計。你試圖解決什麼**問題**? – 2009-08-19 12:22:14

+0

沒有 - 我只是在研究這個問題。我將自己的MVC作爲其中的一部分(冗餘,我知道,但是一個智力練習來幫助我學習)過程。在我的表示層中,有一類對象被視圖控制器用來將局部模板提供給主模塊,我想阻止該對象直接被訪問。 在我看過策略/命令模式後,我想到了它 - 在我看到的例子中,所使用的組件可以直接訪問 - 而且似乎單個入口點才被視爲原則性的一個點。 – sunwukung 2009-08-19 12:58:55

1

可能__calldebug_backtrace效仿類似的東西。

<?php 
class Consumer{ 
    public function __construct($obj){ 
    $this->obj = $obj; 
    } 

    public function doCommand(){ 
    $this->obj->command(); 
    } 
} 

class Consumed { 
    // classes that are aloowed to call private functions 
    private $friends = array('Consumer'); 

    public function __construct(){} 
    private function command() { 
    echo "Executing command in the context of the Consumer. \n"; 
    } 

    public function __call($name, $arguments) { 
    $dt = debug_backtrace(); 
    // [0] describes this method's frame 
    // [1] is the would-be frame of the method command() 
    // [2] is the frame of the direct caller. That's the interesting one. 
    if (isset($dt[2], $dt[2]['class']) && in_array($dt[2]['class'], $this->friends)) { 
     return call_user_func_array(array($this,$name), $arguments); 
    } 
    else { 
     die('!__call()'); 
    } 
    } 
} 

$c = new Consumed; 
$consumer = new Consumer($c); 
$consumer->doCommand(); 

echo 'and now without Consumer: '; 
$c->command(); 

打印

Executing command in the context of the Consumer. 
and now without Consumer: !__call()