【问题标题】:C++/Java Inheritance vs. Delegation vs. etcC++/Java 继承与委托与等
【发布时间】:2010-10-18 04:07:47
【问题描述】:

我正在创建一个类库,其中包含许多不同的选项以进行可能的自定义。例如,您可以设计您的类,使其可以执行 FeatureX(),或者您可以设计您的类,使其可以执行 FeatureY()。

在正常情况下,您只需使用称为 FeatureX 的纯虚方法创建一个接口 IFeatureX,并使用称为 FeatureY 的纯虚方法创建另一个接口 IFeatureY。如果一个类同时具有 FeatureX 和 FeatureY,那么它可以从两者继承,没问题。

我的问题是,如果一个函数/方法需要一个可以同时执行 FeatureX() 和 FeatureY() 的对象怎么办?我如何表达一个类型,最好用 C++,但 Java 的答案也可以帮助确保 FeatureX 和 FeatureY 都可用?

我是否要创建另一个接口 IFeatureXY,它继承自 IFeatureX 和 IFeatureY?好的......如果只有两个功能,我可以摆脱这个。但是如果说... 10 个功能,那么可能的接口数量就会变得庞大。

有没有简单的方法来做到这一点?我尝试使用 C++ 模板和委托来解决问题,但并没有走得太远。我希望有一个简单的解决方案来解决这个问题,而且可能有一个我只是忽略了。

感谢你们提供的任何帮助和建议。

谢谢。

【问题讨论】:

    标签: c++ inheritance delegation


    【解决方案1】:

    如果你不害怕使用模板,你可以将你的函数设为模板,并使用 SFINAE 来检查这两个接口:

    template <class T>
    void my_function(const T& data, typename enable_if_c<
        is_convertible<T*, IFeatureX*>::value && 
        is_convertible<T*, IFeatureY*>::value>::type*=0) {
      ...
    }
    

    这将为扩展两个特性接口的每种类型创建一个方法(请注意,它不需要 SFINAE 技巧即可工作;不受约束的模板可以工作,但是当您传递不满足要求)。

    另一种可能性是创建一个接口 IFeatureXY 扩展两者,并在函数参数中使用它;这有一个缺点,即 确实 实现两个接口的类型,但不是这个联合接口不能用于此方法。

    此外,您可以向函数传递两个参数,每个接口一个,并要求它们是指向同一对象的指针;这是脆弱的,但可以通过制作一些模板类来保存两个指针来加强 - 例如。 product_type&lt;IFeatureX*, IFeatureY*&gt;,它将由相关的单个对象初始化,并且将包含两种类型。

    在 Java 中,您可能可以对有界类型变量做同样的事情(如果它们允许多个边界;我现在不确定)。

    【讨论】:

    • 谢谢,这与我的想法相似,但看起来更强大。
    【解决方案2】:

    首先要问自己是否想做一些不能简单表达的事情,如果是,问问自己这是否真的值得做?

    鉴于您找不到更简单的模型来满足您的需求,您需要考虑选项之间的依赖关系。如果您可以独立于 Feature Y 使用 Feature X,那么让它们成为独立的接口或纯虚拟类(根据语言而定)。

    如果您不能独立使用它们,请创建一个包含两者的类;问问自己为什么要将 FeatureX 和 FeatureY 作为单独的接口,因为这种使用模式表明它们毕竟不是独立的。

    【讨论】:

      【解决方案3】:

      虽然有多种方法可以添加完全不同的功能,但您可能需要考虑这些添加的功能的范围。它们会与您的主类库相关吗? (有人可能会争辩说,如果他们不是,他们不应该成为其中的一部分)

      如果它们有足够的共同点来保证添加功能,您可以寻找装饰器模式 (http://en.wikipedia.org/wiki/Decorator_pattern) 之类的东西。它可以让你绕过一些做这样的事情的不稳定问题。

      【讨论】:

        【解决方案4】:

        如果你想在 c++ 中做,那么多重继承呢?

        【讨论】:

          【解决方案5】:

          可能你的粒度太细了。考虑一个数字类 - 您可以执行乘法、除法、加法、减法等。但是,您不会为这些操作中的每一个创建单独的接口 - 您将创建一个名为 SupportsArithmetic (或其他)的接口,涵盖所有这些操作。

          【讨论】:

            【解决方案6】:

            WCF 有一个非常好的模式,如何使用IExtensionCollection&lt;T&gt;.Find&lt;E&gt;() 来确定某个对象是否支持某个接口(或类)。 IExtensionCollection.

            IFeatureX feature = argument.Find<IFeatureX>();
            
            if (feature != null)
            {
                // Find() returned an instance so there is an implementation
                // of IFeatureX available
            
               feature.FeatureX();
            }
            

            这样您就可以查询您的对象以获取某些接口。 COM+中IUnknown::QueryInterface()中使用了类似的方法。

            【讨论】:

              【解决方案7】:

              为什么需要接口?使用模板:

              template< typename T >
              void some_function( const T& t )
              {
                  // use featureX functions
                  t.fetatureX();
              
                  // use featureY functions
                  t.featureY();
              }
              

              用法:

              SomeClass x; // object with only X feature
              some_function( x ); // compile time error, because featureY() doesn't exists
              

              【讨论】:

                猜你喜欢
                • 2011-07-12
                • 2017-11-07
                • 1970-01-01
                • 2012-10-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-08-31
                • 1970-01-01
                相关资源
                最近更新 更多