在这种情况下如何避免多重继承?

时间:2014-08-30 03:13:30

标签: oop inheritance multiple-inheritance reusability

假设我们有一个包含以下XML的文件:

<document>

   <tagA />
   <tagB />
   <tagC />
   <tag1 />
   <tag2 />
   <tag3 />
   <custom1/>
   <custom2/>

</document>

并假设我们有一个解析器对象来扫描文件。对于文件中找到的每个标记,解析器调用处理程序对象的相应方法:

class Handler{

  function tagA(){ ... }
  function tabB(){ ... }
  function tagC(){ ... }
  function tag1(){ ... }
  function tag2(){ ... }
  function tag3(){ ... }
  function custom1(){ ... }
  function custom2(){ ... }

}

现在,假设我们要构建一个框架来处理上述类型的文件。为了确保代码的可重用性,我们可以将上面的类拆分为不同的(更专业的)类:

class LettersHandler{

  function tagA(){ ... }
  function tabB(){ ... }
  function tagC(){ ... }

}

class NumbersHandler{

  function tag1(){ ... }
  function tag2(){ ... }
  function tag3(){ ... }

}

为了编写上述文件的处理程序,程序员可以利用框架并仅实现缺少的方法(使用OOP继承):

class Handler extends LettersHandler, NumbersHandler{

  function custom1(){ ... }
  function custom2(){ ... }

}

根据文件的内容,程序员可能只选择从两个类继承(如上例所示)或者不继承。

现在,假设框架支持许多预构建处理程序:

class LettersHandler{ ... }
class NumbersHandler{ ... }
class SymbolsHandler{ ... }
etc...

如果编程语言支持多重继承,程序员可以继承框架提供的一个或多个类来处理特定文件(根据文件中包含的标签)。

现在,我的问题是:

如果编程语言不支持多重继承但只支持单继承,那么实现上述情况的最佳方法是什么?

使用多重继承有一种简单的方法吗?

我已经读过多重继承通常被认为是一种不好的做法,但我真的无法理解如何在不使用它的情况下实现上述情况。

2 个答案:

答案 0 :(得分:0)

更改解析器,使其接受一个处理程序数组而不是一个处理程序,并让它依次为每个标记调用每个处理程序。如果处理程序无法处理标记(通过测试方法的存在,或者通过基类的方法返回一些“未实现的”sigil值),则调用下一个处理程序。

如果无法修改解析器,请实现一个新的处理程序,它接受一个处理程序数组并委托给它们,就像它是上面修改过的解析器一样。

这实质上是将程序的类型从程序的类型转移到程序数据中的结构。

答案 1 :(得分:0)

  1. 创建一个名为TagHandler的基类。

    // A C++ incarnation of such a class.
    class TagHandler
    {
       virtual processTag(std::string const& tagName,
                          ..., // Any additional arguments that makes sense
                         ) = 0; 
    
    };
    
  2. 为客户提供基于标签名称注册TagHandler的机制。制定一些策略决策,决定如何处理为给定标记名称注册处理程序的多个客户端。你想提出例外吗?最后一个赢了吗?你允许多个TagHandler吗?

    class TagProcessor
    {
       public:
         static void registerTagHandler(std::string const& tagName,
                                        TagHandler* tagHandler)
         {
            // Do the needful to register the TagHandler based on policy.
         }
    };
    
  3. 提供一个在上面的类中以黑盒方式处理标签的功能。

    class TagProcessor
    {
       public:
    
         static void processTag(std::string const& tagName,
                                ..., // Any additional arguments that makes sense
                                )
         {
           // Look for the TagHandler(s) given the tag name.
           // If found, call the processTag() function.
           // Deal with non-existing TagHandler.
         }
    
    
    };
    
  4. 创建TagHandler的子类型以处理各种标记。

    class TagAHandler : public TagHandler
    {
      public:
        virtual processTag(std::string const& tagName,
                          ...)
         {
           // Do the needful to process the tag
         }
    };
    
  5. 注册TagHandler以处理“tagA”

    TagProcessor::register("tagA", new TagHandler());
    
  6. 在解析器代码中调用TagProcessor::processTag