2009-08-19 86 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()