如何强制实现者做某事

时间:2010-11-03 12:07:25

标签: c++ oop

假设我有以下类:

class X;
class Y;

class Collection
{
   public:
      virtual void AddItemX(X*) = 0;
      virtual void AddItemY(Y*) = 0;
      //So on...
};

class Collector
{
   public:
      virtual void Fill(Collection&) = 0;
};

有没有办法确保Collector类的实现将填充传递的Collection类中的所有必需项?

6 个答案:

答案 0 :(得分:3)

给定已知数量的AddItemX()调用的一种方法是将这些AddItem()函数移动到受保护的并使Collection类跟踪添加和数字,例如:

(我实际上不喜欢这个解决方案,哈哈,但考虑到你的设计就足够了:)。

class X;
class Y;

class Collection
{
private:
    int m_nItems;
    int m_nItemsAdded;

protected:
    virtual void AddItemXImpl(X&) = 0;
    virtual void AddItemYImpl(Y&) = 0;

public:
    Collection() : m_nItems(2), m_nItemsAdded(0){};

    void AddItemX(X& _x) {m_nMethodsAdded++; AddItemXImpl(_x); };
    void AddItemY(Y& _y) {m_nMethodsAdded++; AddItemYImpl(_y); };

    // function to find out if we're filled
    bool isFilled() const {return(m_nItemsAdded == m_nItems); };
}; // eo class Collection

编辑:为了澄清,您的收藏家可以这样实施:

class Collector
{
protected:
    virtual void FillImpl(Collection& _collection) = 0;

public:
    void Fill(Collection& _collection)
    {
        FillImpl(_collection);
        if(!_collection.isFilled())
            throw(std::exception("Not filled dammit!"));
    };
}; // eo class Collector

答案 1 :(得分:2)

是的,使用模拟集合为收集器编写unit test

编译执行时间?否。

运行时执行?是的,Collection类中有很多开销。

答案 2 :(得分:1)

你错过了上面的东西,叫什么叫Collector :: Fill()?在那里你需要检查收集已被填充......

编辑:您是否可以控制调用Collector :: Fill()的位置?这是唯一可以检查集合是否已正确填充的地方。另一个选择是按值传递所有内容,并在复制构造函数(或赋值)中检查..

答案 3 :(得分:1)

在这种情况下,断言语句可以是记录和测试某些内容符合您的假设的好方法。

答案 4 :(得分:1)

当您为将来的开发人员实施一种方法时,您放弃的一件事就是控制他们如何做到这一点。您可以添加一条评论来提出您的建议,但是他们可以根据他们的子类做适当的评论。毕竟,你永远无法确定你的课程将如何在路上使用。

答案 5 :(得分:0)

您可以修改类定义以鼓励正确使用,方法是在Collection构建时检查Collector有效性,禁止Collector的默认构造或修改封装的Collection 。让Collector构造函数使用纯虚方法验证收集器。

这并不保证正确性 - Collection实现者​​仍然可以通过允许格式错误的子类来作弊 - 但通过更清楚地表达您想要的内容来支持它。

class X;
class Y;

class Collection
{
   public:
      virtual void AddItemX(X*) = 0;
      virtual void AddItemY(Y*) = 0;
      //So on...

      virtual bool ensureValid() = 0;
};

class Collector
{
   public:
      Collector (const Collection coll&) : _coll(coll)
      {
         if (!coll.ensureValid())
         {
           // throw an error
         }
      }

   private:
      Collector();

   protected:
      const Collection _coll;
};