简体   繁体   English

组合与继承依赖注入

[英]Composition vs. Inheritance dependency injection

I have a Parser with three classes of objects: the parser itself, Token s, and State s. 我有一个包含三类对象的Parser:解析器本身, Token s和State s。 The Parser generates tokens from the lexer. 解析器从词法分析器生成令牌。 Everything is black boxed, so the tokens know nothing about the parser state or the parser, and the state knows nothing of the tokens. 一切都是黑盒子,因此令牌对解析器状态或解析器一无所知,并且状态对令牌一无所知。 A fairly simple version of the arrangement: 一个相当简单的安排版本:

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;
   }
}

The problem I'm running into is that sometimes when a state changes, the parser needs to take some action (such as add a rule to the tree when the ending-rule token is reached). 我遇到的问题是,有时当状态发生变化时,解析器需要采取一些操作(例如在到达结束规则标记时向树中添加规则)。 Only the State knows that, so it is up to the state to tell the parser what to do. 只有State知道这一点,所以由国家来告诉解析器该做什么。 Problem is getting the Parser to the State . 问题是让Parser进入State I could inject the Parser in the state constructor, but not every State needs the parser, and that would lead to a lot of duplicate code (unless I had a base class for the State s and the Parser was a protected member, but I want to avoid extending anything). 我可以在状态构造函数中注入Parser ,但不是每个State需要解析器,这会导致很多重复的代码(除非我有一个State的基类, Parser是受保护的成员,但我想要避免扩展任何东西)。 I could also inject the Parser in the state methods that need it, but I have a similar problem: that would be a lot of duplication, and not all of the State implementations would need the parser for given methods. 我也可以在需要它的state方法中注入Parser ,但是我有一个类似的问题:这将是很多重复,并不是所有的State实现都需要给定方法的解析器。

So my question is how can I get the State to know about the Parser when it needs to without unnecessary inheritance or code duplication? 所以我的问题是,如果没有不必要的继承或代码重复,我怎样才能让State知道Parser If I need another class that's perfectly acceptable. 如果我需要另一个完全可以接受的课程。


In case this is difficult to follow, here is an "unraveled" version: 如果这很难理解,这里是一个“解开”的版本:

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;
         }
      }
   }
}

The answer to this question could apply to other languages as well, but I know this would be easier to do in languages that allow overloading. 这个问题的答案也适用于其他语言,但我知道在允许重载的语言中这会更容易。 PHP does not. PHP没有。

PHP 5.4 introduces traits: http://php.net/manual/en/language.oop5.traits.php PHP 5.4引入了特征: http//php.net/manual/en/language.oop5.traits.php

Perhaps you could use traits as a halfway between inheritance and injection. 也许你可以在继承和注入之间使用特征。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM