PHP OOP:将对象指定为属性时执行某些操作

时间:2012-12-18 20:34:51

标签: php oop getter-setter

考虑这个假设情景:

我有一个Stomach类,它具有contents属性,应该为其分配类Food的对象。一种方法是使用一种定位器,例如, setContents($food)

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

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

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

3 个答案:

答案 0 :(得分:5)

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

为了确保正确的对象 eaten ,您可以定义Interface(Say Food )。该接口可以定义方法setEaten()。胃(虽然我更喜欢哺乳动物或类似的东西,实际上可以吃)然后可以调用setEaten()。

由于它在评论中引起了一些争议,我想指出一个对象定义应该尽可能地反映它实际上做了什么。要减少对象耦合,最好避免直接访问其他类的对象属性,但是当它有意义时使用setter而不是动作没有任何问题(注意我在定义中使用了一个) Food ),它通常取决于开发人员的观点。

然而,这里有道理。考虑一下“猴子吃香蕉”的情况(为了简单起见,请允许我用空气来实现香蕉)。

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

完美。现在让我们尝试一下setter。

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

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

答案 1 :(得分:2)

我同意@dualed关于eat方法。这就是说实现此方法以使所有属性成为私有/受保护的方式,然后使用__get / __set代理setter。

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依赖于方法在类层次结构中定义。

答案 2 :(得分:1)

__set功能会在这里帮到你。但请确保您没有在类中定义的任何名为contents的属性。这样做

class Stomach{
    private $props = array();
    public __set($prop, $value){
        if($prop === 'contents' and $value instanceof Food){
            $this->prop[$prop] = $value;
        }
    }
}