在Effective Objective-C中,Matt Galloway建议如下:
“始终在最深处导入标头。这通常意味着在标头中声明类并在实现中导入相应的标头。这样做可以避免尽可能地将类耦合在一起。”
使用此练习项目的问题是,使用您的类的任何内容都需要导入前向声明类。这似乎是客户端的一个缺点,只是为了避免可能增加的编译时间。耦合的减少也没有意义,因为通过使用前向声明,耦合已经建立。这个建议是一个好的做法吗?
答案 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"是一个好主意。所有这些信息都会进入你自己班级的公共界面。