2012-04-24 7 views
3

私はパーサ自体が3クラスのオブジェクトを持っています:パーサ自体、Token、およびStateです。パーサーは、レクサーからトークンを生成します。すべてが黒いボックスになっているので、トークンはパーサ状態またはパーサーについては何も知らず、状態にはトークンは何も分かりません。配置のかなり単純なバージョン:コンポジションと継承の依存性注入

class Parser { 
    public function parse() { 
     $this->state = new StEmpty; 
     while ($token = $this->lexer->get()) { 
     $this->state = $this->token->expect($this); 
     } 
    } 
    public function stateStart() { 
     return $this->state->stateStart(); 
    } 
} 
class StartToken { 
    public function expect(Parser $parser) { 
     return $parser->stateStart(); 
    } 
} 
class StEmpty { 
    public function stateStart() { 
     return new StStart; 
    } 
} 

私はに実行している問題は、ときの状態が変化し、時には、パーサは、このようなときending-ツリーにルールを追加するなど、いくつかのアクションを(行う必要があることですルールトークンに達する)。 Stateだけがそのことを知っているので、パーサーに何をすべきかを伝えるのは状態までです。問題は、StateParserを取得しています。私はParserを状態コンストラクタに挿入することができましたが、すべてStateにパーサが必要というわけではありませんし、それは多くの重複コードにつながります(Stateの基底クラスとParserが保護されたメンバーでない限り)何かを広げるのを避けるため)。私はまた、それを必要とするstateメソッドにParserを注入することができましたが、私は同様の問題があります:それは多くの重複であり、State実装のすべてが与えられたメソッドに対してパーサを必要としません。

私はStateに、Parserについて知ってもらうために、どうすれば不要な継承やコードの重複がないようにする必要がありますか?私が完全に受け入れられる別のクラスが必要な場合。場合


これは、ここでは、従うことは困難であり、「ほぐれ」バージョンです:この質問への答えは、他の言語にも適用することができる

class Parser { 
    public function parse() { 
     $this->state = 'StEmpty'; 

     while ($token = $this->lexer->get()) { 
     switch ($token) { 
      case 'StartToken': 
       switch ($this->state) { 
        case 'StEmpty': 
        $this->state = 'StStart'; 
        break; 
       } 
       break; 
     } 
     } 
    } 
} 

が、私は、これは容易になるだろう知っています過負荷を許容する言語で行うこと。 PHPはそうではありません。

+0

「何かを広げたくない」理由を説明できますか? OOコードに関しては、これは非常に奇妙なことです。 – FtDRbwLXw6

+0

@drrcknlsn継承を嫌う人々の小さな(私は)先駆けがあります。もし必要なら、私は諦めますが、すべての州がパーサーにアクセスする必要はないので、これは適切ではないかもしれません。 –

+0

私はそのような事を聞いたことがない。 OO設計の主な利点の1つは継承です。アクセスを必要とする子どもの場合は、複数のレベルの継承が行われます。アクセスが必要なものは、Parserが挿入されたクラス(基本クラスを拡張するクラス)を拡張します。アクセスを必要としないものは基本クラスを拡張するだけです。もしあなたが望むなら、あなたは構図でこれを解決することもできます... – FtDRbwLXw6

答えて

1

PHP 5.4の特徴を紹介します。http://php.net/manual/en/language.oop5.traits.php

おそらくあなたは、継承と注入の間の途中としての特性を使用することができます。

+0

もし私がPHP 5.4を使うことができれば、特性は素晴らしいでしょう。 –