私はパーサ自体が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
だけがそのことを知っているので、パーサーに何をすべきかを伝えるのは状態までです。問題は、State
にParser
を取得しています。私は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はそうではありません。
「何かを広げたくない」理由を説明できますか? OOコードに関しては、これは非常に奇妙なことです。 – FtDRbwLXw6
@drrcknlsn継承を嫌う人々の小さな(私は)先駆けがあります。もし必要なら、私は諦めますが、すべての州がパーサーにアクセスする必要はないので、これは適切ではないかもしれません。 –
私はそのような事を聞いたことがない。 OO設計の主な利点の1つは継承です。アクセスを必要とする子どもの場合は、複数のレベルの継承が行われます。アクセスが必要なものは、Parserが挿入されたクラス(基本クラスを拡張するクラス)を拡張します。アクセスを必要としないものは基本クラスを拡張するだけです。もしあなたが望むなら、あなたは構図でこれを解決することもできます... – FtDRbwLXw6