是否可以根据需要继续向基类(接口)添加虚拟方法?

时间:2017-07-13 15:30:44

标签: c++ oop design-patterns polymorphism

让我们考虑以下OOP结构。基类(接口)是所谓的节点'类。另外两个类继承自' Node',即' ElementNode' TextNode'。我需要使用多态容器(vector>)。在某些时候,我需要从通过向量提取的元素中获取一些类成员,该元素被向上转换隐藏,例如来自' TextNode'的文本。我的问题是,从设计的角度来看,继续向基类添加虚拟方法是很好的。节点' Node'为了获得隐藏成员的访问权限。另一种选择是使用向下铸造。设计是否存在缺陷,如果它是您建议的替代方案?

C ++中的示例代码:

class Node {
public:
     Node() {};
     virtual ~Node() {};

     NodeTypes getNodeType() const { return nodeType; };
     virtual std::vector<std::shared_ptr<Node>> &getChildren() = 0;
     virtual void pushChild(std::shared_ptr<Node>) = 0;

private:
     NodeTypes nodeType;
     std::vector<std::shared_ptr<Node>> children;
};

class ElementNode : public Node {
public:
     ElementNode(HtmlElements, Node*);

     void setTag(HtmlElements);

     //Inherited methods.
     std::vector<std::shared_ptr<Node>> &getChildren();
     void pushChild(std::shared_ptr<Node>);
     Node* getFather() const;
};  

class TextNode : public Node {
public:
     TextNode(std::string);
     std::string getText() const;
     void setText(std::string);

     //Inherited methods.
     std::vector<std::shared_ptr<Node>> &getChildren();
     void pushChild(std::shared_ptr<Node>);
     Node* getFather() const;

private:
    std::string text;
 };

2 个答案:

答案 0 :(得分:2)

答案取决于设计的成熟度。

设计早期,当然。这很容易。只需将新的抽象方法添加到基类中,编译器会告诉您是否忘记在派生类中实现它们。一块蛋糕。

在成熟的设计和大型项目中,它可能并不那么容易。如果新方法对某些派生类没有意义怎么办?或者如果它们在使用界面的每个地方都没有意义呢?我已经看到它发生了,并且回答了#34;如果......&#34;是,你为特殊情况修改了变通方法。让一切恢复正常可能需要几个月的时间,当你完成后,系统变得更加丑陋,更脆弱,更难以维护。

在其他团队使用的图书馆中,这是一场灾难。你最终打破了你从未听说过的项目构建。您可能最终在新的主要版本中发布更改,然后您发现自己必须同时支持新版本旧版本,因为您的某些客户并不想要更改

除非您仍处于早期设计阶段,否则正确的答案是定义一个全新的界面。旧界面因某种原因而存在。由于这个原因,人们仍在使用它。您要进行的更改是针对的原因。那么,为什么不定义一个支持新原因的新界面,并保留旧原因呢?如果有意义,新界面甚至可以继承旧界面。

答案 1 :(得分:2)

根据需要添加方法&#34;&#34;最终将与SOLID的Interface Segregation Principle发生冲突。

并非Node的所有客户都需要知道所有变种,对吧?这意味着当您的基类变得臃肿时,客户将被迫了解所有细节。这听起来很像Robert Martin在ISP定义中给出的Xerox Printer示例。

getText()添加到基类意味着您违反了Liskov Substitution Principle的SOLID,因为某些节点不支持该方法。

您的问题是如何识别存储在向量中的节点类型。我说你应该根据利斯科夫替代原则重新考虑你的设计部分。向下投入可能有两个邪恶中的较小者。