3

考虑这个假设场景:

我有一个Stomach类,它有一个contents属性,类的对象Food应该分配给它。一种方法是使用一种 setter,例如setContents($food).

但是让我们假设我们直接分配食物,如$stomach->contents = $orange.

还假设每当一个Food对象被分配给我们时,contents我们需要将对象的eaten属性更改为true。有没有办法在不使用分配给它的对象的方法的情况下做到这一点(在这种情况下,是$stomach's setter)?

基本上,我的问题是:当一个对象作为属性分配给另一个对象时,我们可以调用一个方法吗?另外,即使有可能,这是糟糕的设计吗?抱歉,如果这是一个愚蠢的问题,所有这些对我来说都很新鲜。

4

3 回答 3

5

这里最好的 OOP 解决方案是创建一个指示动作的方法,例如eat().

为了确保正确的对象被吃掉,你可以定义一个接口(比如食物)。这个接口可以定义一个方法 setEaten()。胃(虽然我更喜欢哺乳动物或类似的可以吃的东西)然后可以调用 setEaten()。

由于它在评论中引起了一些争议,我想指出一个对象定义应该尽可能地反映它的实际作用。为了减少对象耦合,最好避免直接从其他类访问对象属性,但是在有意义的情况下使用 setter 代替操作没有任何问题(请注意,我在Food的定义中使用了一个),而且它可能经常取决于开发者的观点。

然而,这里说得通。考虑“猴子吃香蕉”的情况(为简单起见,请允许我凭空实现香蕉)。

$m = new Monkey();
$m->eat(new Banana());

完美的。现在让我们尝试一个二传手。

$m->setContents(new Banana());

现在我们有一个问题,猴子已经包含了很多东西,比如骨头、血液、肌肉和大脑等。所以 setContents 在这里没有意义。您可以尝试$m->getStomach()->setContents(new Banana()),但这只会增加对象耦合。

于 2012-12-18T20:36:49.770 回答
2

我同意@dualed 关于该eat方法的看法。这就是说实现这一点的方法是使所有属性成为私有/受保护的,然后使用__get/__set代理到设置器。

class Stomach {

   protected $contents;


   public function setContents(Food $food) {
      $this->contents = $food;
      $food->eaten = true;    
   }


   public function __set($name, $value) {
      $method = array($this, 'set' . $name);
      if(is_callable($method)) {
         return call_user_func_array($method, array($value));
      }
   }

  public function __get($name) {
     $method = array($this, 'get'.$name);
     if(is_callable($method)) {
        return call_user_func($method);
     }
  }
}

你会注意到我使用is_callable的不是,method_exists因为如果你正在使用虚拟方法处理一些复杂的事情is_callable,应该考虑到这些,而method_exists依赖于类层次结构中定义的方法。

于 2012-12-18T20:40:55.327 回答
1

__set函数将在这里为您提供帮助。但请确保您没有contents在 class 中定义任何名为的属性。像这样做

class Stomach{
    private $props = array();
    public __set($prop, $value){
        if($prop === 'contents' and $value instanceof Food){
            $this->prop[$prop] = $value;
        }
    }
}
于 2012-12-18T20:41:30.023 回答