C ++:组合接口

时间:2010-01-04 19:48:23

标签: c++ class interface composition

所以我花了一些时间考虑这个问题并且一直在谷歌寻找'解决方案'(解决方案很可能是一个偏好的问题,但我不确定这一点)。以下是我遇到的问题,但问题可以应用于很多关于构图的情况。

我有一个类Color,包含红色,绿色,蓝色和alpha的成员。其中每个都有一个set和get成员函数。很简单。

class Colour
{
    public:
        float getRed();
        void setRed(float);
        float getGreen();
        void setGreen(float);
        ...
    private:
        float red;
        float green;
        ...
};

我将在其他类中使用此类来指示它们的颜色,例如(省略构造函数和析构函数):

class ColourableObject
{
    private:
        Colour colour;
};

现在我的问题是:这个ColourableObject类如何最好地访问这个Color对象?是否最好直接检索Color对象以访问其成员函数,如下所示:

class ColourableObject
{
    public:
        Colour& getColour();
    private:
        Colour colour;
};

或者,最好是将ColourableObject类赋予其自己的set并获取color的函数,其中对Color对象执行操作,如下所示:

class ColourableObject
{
    public:
        float getRed();
        void setRed(float);
        ...
    private:
        Colour colour;
};

对我而言,前者是最合乎逻辑的,因为通过简单地直接对此Color对象进行操作,为每个需要此Color对象的类添加功能会省去很多麻烦。

但是,后者是否更容易更改ColourableObject类?更不用说colourableObject.getColour()。setRed(x)对我来说似乎不太自然,因为get和set相互冲突。

我可能完全采用了错误的方法。我对C ++比较陌生,所以我愿意学习!所以问题是,我应该使用前一种方法,后一种方法,还是一种完全不同的方法?

6 个答案:

答案 0 :(得分:3)

不要直接回答你的问题,但我会摆脱所有的设置者(在任何情况下通常都是一个不好的标志,并使用构造函数):

Color c = Color( 123, 17, 77 );

其中三个构造函数参数是RGB值。

答案 1 :(得分:1)

我可能会重新创建你的课程,以防你需要添加其他颜色,如Orange,Purple,Cyan或Crayola的新Smooky Applewood!

类似于基色类,并通过引入新颜色对该基类起作用。 这样,你正在处理哪种颜色并不重要。这都是一个黑盒子。这也将回答你的第二个问题,因为它不需要重新定义你的setColor和getColor名称方法。他们不需要知道或关心你指的是什么颜色。

我觉得Code Complete(这本书)有一个部分对于看到有太多get / set方法的类有点小问题。它通常归结为错误的做法

答案 2 :(得分:1)

在这种情况下,你使用getter和setter并没有多大意义。您也可以让float成员Colour公开。除非您需要对多个私有成员进行验证或操作,否则请继续公开,并创建一个构造函数来适当初始化Colour

关于ColourableObject,您应该问的问题是:其他不相关的类是否需要访问对象的Colour成员?他们是否需要对其进行更改?如果那些 的答案是“不”,我会说你根本不应该对那个对象有任何吸气剂或设定器。否则,除非您需要进行验证或其他状态更改,否则只需将Colour公开。

答案 3 :(得分:1)

DRY principle支持您的第一个选项,提供对Colour对象的访问权限。

此外,您可能希望更改

    Colour& getColour();

    const Colour& getColour();
    void setColour( const Colour& );

...因为这将确保您的ColourableObject始终知道其颜色何时发生变化。

答案 4 :(得分:1)

最终,答案取决于您(或不希望)如何限制对嵌入Color对象的访问。

在你的第一选择中......

class ColourableObject
{
public:
    Colour& getColour();
private:
    Colour colour;
};

...你根本就没有限制访问权限。如果用户可以通过getColour()访问私人会员,那么将其设为私有的重点是什么?您也可以跳过中间步骤,然后执行此操作:

class ColourableObject
{
public:
    Colour colour;
};

当这样做时,一个人可以直接引用数据成员及其所有函数,例如C.colour.getRed();(假设C是ColourableObject)

现在,假设你想以某种方式限制最终用户 - 他不能设置绿色或蓝色,但你可以让他设置红色。在这种情况下,您可能想要使用第二种选择:

class ColourableObject
{
public:
    float getRed();
    void setRed(float);
    ...
private:
    Colour colour;
};

这是因为ColourableObject的用户只能访问您的公共功能,而不能访问基础私有成员。如果您希望在最终用户和颜色选择之间有一些中间步骤,这个基本原理也适用。例如,以下内容:

class ColourableObject
{
public:
    void setMood(enum Mood);
private:
    Colour colour;
};

void ColourableObject::setMood(enum Mood)
{
   if(Mood == HAPPY) colour.setRed(3);
   if(Mood == SAD)  colour.setBlue(11);
   ...
}

最后,您可以执行混合操作,使colour数据成员保持公开状态,但也会为该数据成员添加其他访问者。

<强>要点:

  • 第一种方法:

    • Pro:与颜色的接口贯穿始终。
    • Con's:使数据成员公开。
  • 第二种方法:

    • Pro's:封装数据。对Color的界面的未来更改只会破坏您的代码,而不是最终用户。
    • Con's:您必须重新实现您希望最终用户能够使用的Color界面的任何部分。

答案 5 :(得分:0)

就个人而言,在Colorable成员的情况下,我更倾向于放弃“获取”部分:

colorableObject.Color().setRed(1.0f);

正如你所说,这完全是个人偏好(就像拼写一样!:)但是这样,对我来说它看起来像是一个“属性”,而不是一个getter / setter方法。