2

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

我有一个类,颜色,包含红色、绿色、蓝色和 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 类提供自己的集合并获取颜色函数,其中作用于 Color 对象,如下所示:

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

对我来说,前者是最合乎逻辑的,因为它可以通过简单地直接作用于这个 Color 对象来为每个需要这个 Color 对象的类添加功能,从而省去很多麻烦。

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

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

4

6 回答 6

4

不直接回答你的问题,但我会摆脱所有的设置器(通常在任何情况下都有设置器的坏信号),并使用构造函数:

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

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

于 2010-01-04T19:52:34.390 回答
1

如果您可能需要添加其他颜色,例如橙色、紫色、青色或 Crayola 的新 Smooky Applewood,我可能会重新创建您的课程!

有点像基色类,并通过引入新颜色来作用于该基类。这样,您处理的颜色无关紧要。这都是一个黑匣子。这也将回答您的第二个问题,因为您不必重新定义您的 setColor 和 getColor 名称方法。他们不需要知道或关心您指的是什么颜色。

我认为 Code Complete(这本书)有一个部分对查看具有太多 get/set 方法的类有点谨慎。它通常归结为错误的做事方式。

于 2010-01-04T19:53:46.807 回答
1

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

至于ColourableObject,您应该问的问题是:其他不相关的类是否需要访问对象的Colour成员?他们需要对其进行更改吗?如果其中任何一个的答案是“否”,我会说您根本不应该在该对象上使用任何类型的 getter 或 setter。否则,同样,除非您需要进行验证或其他状态更改,否则只需Colour公开即可。

于 2010-01-04T19:54:38.350 回答
1

DRY 原则支持您的第一个选项,提供对Colour对象的访问。

此外,您可能希望更改

    Colour& getColour();

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

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

于 2010-01-04T19:55:28.660 回答
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;
};

这是因为 a 的用户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's: 色彩接口贯穿始终。
    • 缺点:公开数据成员。
  • 第二种方法:

    • 专业人士:封装数据。未来对 Colour 界面的更改只会破坏您的代码,而不是最终用户的代码。
    • 缺点:您必须重新实现您希望最终用户能够使用的 Colour 界面的任何部分。
于 2012-03-29T01:44:41.940 回答
0

就 Colorable 的成员而言,就个人而言,我更喜欢删除“get”部分:

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

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

于 2010-01-04T21:48:08.773 回答