3

次の架空のシナリオを考えてみましょう。

クラスのオブジェクトを割り当てる必要があるプロパティStomachを持つクラスがあります。これを行う 1 つの方法は、一種のセッターを使用することです。contentsFoodsetContents($food)

しかし、 のように食べ物を直接割り当てるとしましょう$stomach->contents = $orange

Foodまた、オブジェクトが に割り当てられるたびに、オブジェクトのプロパティをcontentsに変更する必要があるとします。割り当てられているオブジェクトのメソッドを使用せずにそれを行う方法はありますか (この場合、のセッター)?eatentrue$stomach

基本的に、私の質問は次のとおりです。オブジェクトがプロパティとして別のオブジェクトに割り当てられるたびに、メソッドを呼び出すことができますか? また、出来たとしても設計が悪いのでしょうか?これがばかげた質問である場合は申し訳ありませんが、これはすべて私にとってかなり新しいものです。

4

3 に答える 3

5

ここでの最適な OOP ソリューションは、 のようなアクションを示すメソッドを作成することeat()です。

適切なオブジェクトが食べられるようにするために、インターフェイス(Say Food )を定義できます。このインターフェイスは、メソッド setEaten() を定義できます。胃 (私は実際に食べることができる哺乳動物または類似のものを好みますが) は、setEaten() を呼び出すことができます。

コメントでいくつかの論争が巻き起こったので、オブジェクト定義は実際の動作を可能な限り正確に反映する必要があることを指摘したいと思います。オブジェクトの結合を減らすには、他のクラスからオブジェクト プロパティに直接アクセスすることを避けるのが最善ですが、意味がある場合はアクションの代わりにセッターを使用しても問題はありません ( 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関数が役立ちます。ただし、 class で定義されたという名前のプロパティがないことを確認してくださいcontents。このようにしてください

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 に答える