你应该尽可能多地申报一个班级吗?

时间:2014-12-25 15:57:37

标签: objective-c forward-declaration

Effective Objective-C中,Matt Galloway建议如下:

“始终在最深处导入标头。这通常意味着在标头中声明类并在实现中导入相应的标头。这样做可以避免尽可能地将类耦合在一起。”

使用此练习项目的问题是,使用您的类的任何内容都需要导入前向声明类。这似乎是客户端的一个缺点,只是为了避免可能增加的编译时间。耦合的减少也没有意义,因为通过使用前向声明,耦合已经建立。这个建议是一个好的做法吗?

1 个答案:

答案 0 :(得分:2)

  

使用此练习项目的问题是,使用您的类的任何内容都需要导入前向声明类。

我认为你误解了Matt的建议:我的想法是将类一起向前声明与在声明中使用它的类,以便你的标题可以自己使用,无需客户做任何特别的事情。

以下是一个简单示例:假设您希望在班级SingleWidget中使用班级DoubleWidget。但是,您的类公开的接口始终通过指针或引用使用SingleWidget;只有实现调用SingleWidget的方法。马特的建议就是这样做

DoubleWidget.h

// Use forward declaration in the header
class SingleWidget;

class DoubleWidget {
    SingleWidget &one;
    SingleWidget &two;
public:
    DoubleWidget(SingleWidget& a, SingleWidget& b) : one(a), two(b) {}
    void play();
};

DoubleWidget.cpp

#include "SingleWidget.h"
// Include the header when you cannot avoid including it
#include "DoubleWidget.h"

void DoubleWidget::play() {
    one.play();
    two.play();
}

而不是:

DoubleWidget.h

// Do not include the header where a forward declaration is sufficient
#include "SingleWidget.h"

class DoubleWidget {
    SingleWidget &one;
    SingleWidget &two;
public:
    DoubleWidget(SingleWidget& a, SingleWidget& b) : one(a), two(b) {}
    void play();
};

DoubleWidget.cpp

#include "DoubleWidget.h"

void DoubleWidget::play() {
    one.play();
    two.play();
}

请注意,在这两种情况下,DoubleWidget类的用户都可以包含DoubleWidget.h标头。但是,在第二种情况下,用户也可以在不要求的情况下获得SingleWidget类的完整定义。

  

耦合的减少也没有意义,因为通过使用前向声明,耦合已经建立。

你确实在那里得到了一些耦合,但它非常弱:你的班级知道另一个班级存在,而且它是关于它的。相反,当你包含头时,你的类知道另一个类的所有内容:它知道它的结构,它的成员函数,其他类依赖的类,等等。没有" dump"是一个好主意。所有这些信息都会进入你自己班级的公共界面。