该项目的目标是:使用以界面为中心的设计。基本上,我们声明仅公共(public)纯函数的类,并从它们继承真实的类。

现在出现一个问题-如何重用实用程序功能?

这是一个例子:

class InterF1 {
  public:
    int f1() = 0;
    int g1() = 0;
};

class InterF2 {
  public:
    int f2() = 0;
};

class C1: public InterF1 {
  public:
    int f1();
    int g1();
};


class C2: public InterF1, InterF2 {
  public:
    int f1();
    int g1();
    int f2();
};

当我实现C1::f1()和C2::f1()时,我看到这两个函数之间的代码重复。我应该如何删除重复项?

这是我的想法:

1)我可以像这样向接口(interface)类添加保护:
class InterF1 {
  public:
    int f1() = 0;
    int g1() = 0;
  protected:
    int util();
    int convenient_var_calculated_by_util;
};

在上述设计中,C1::f1()和C2::f2()都可以调用util()。

2)我可以抽象一个新接口(interface):
class UtilI {
    public:
      int util(int in_var) = 0;
};

在此设计中,将InterF1,C1和C2更改为
class InterF1 {
  public:
    int f1(UtilI u) = 0;
    int g1() = 0;
};

class C1: public InterF1 {
  public:
    int f1(UtilI u);
    int g1();
};


class C2: public InterF1, InterF2 {
  public:
    int f1(UtilI u);
    int g1();
    int f2();
};

C1::f1()和C2::f1()都调用UtilI API。

解决方案2似乎更符合我们的“以界面为中心”的目标,而且看起来确实更好。但是我有一个担忧,InterF1和InterF2本身应该比UtilI更高级别的抽象,后者是实现细节的更多内容,我是否将这两个级别混合在一起?换句话说,如果以后更改实现,我将需要再次更新f1()和f2()签名,这听起来不对。

解决方案1似乎很方便,但对我来说似乎不那么“纯粹”,我在这里教条太多吗?

最佳答案

通常,我会说您应该将通用实现放在基类中-但是您有一个要求,即基类是纯虚拟的。因此,我建议:

  • 创建一个中间实现类

    如果每个想要实现InterF2的类也都想实现InterF1,则这种方法是可行的。

    方法是实现
    class InterF1Impl: public InterF1 {
      public:
        int f1();
        int g1();
    }
    

    然后C1C2都可以从InterF1Impl派生,后者实现了常见的f1()g1()方法。

    但是,如果您有另一个类C3 : public InterF2,则该方法不能很好地扩展,该类希望与f2()共享C2的实现,但又不想实现InterF1

    另一种(更好的)方法是
  • 使用组成包括实现类

    在这种方法中,如上所述实现InterF1Impl: public InterF1,但是不要派生C1: public InterF1Impl,而是让InterF1Impl作为C1类的一部分。
    class C1: public InterF1 {
      private:
        InterF1Impl * f1impl;
      public:
        int f1();
        int g1();
    }
    
    C1::f1()C1::g1()方法仅从f1impl调用相应的方法。

    这样,如果您需要f2()的通用实现,则还可以实现InterF2: public InterF2,并且C2可以通过类似的方式实现:
    class C2: public InterF1, InterF2 {
      private:
        InterF1Impl * f1impl;
        InterF2Impl * f2impl;
      public:
        int f1(); /* calls f1impl->f1() */
        int g1(); /* calls f1impl->g1() */
        int f2(); /* calls f2impl->f2() */
    }
    

    如果您以后需要此类,则另一个类可以仅使用InterF2的实现,而无需也实现InterF1
  • 10-06 15:22