避免仅抽象父类的头的#import

时间:2010-01-12 16:23:03

标签: objective-c inheritance import abstract-class header-files

我开发了CHDataStructures,一个Cocoa数据结构库,以补充Foundation中的那些。它包括共享公共实现细节的a fair number of classes(堆栈,队列和出队),因此使用我认为是抽象的公共父类来设计它们是有意义的(Objective-C本身并不强制执行此概念) 。例如,CHAbstractCircularBufferCollection几乎封装了在封面下使用循环缓冲区的结构的所有逻辑。它的子类继承核心行为,并符合适当的协议,因此只添加与该协议相关的方法。 (因此队列不会暴露堆栈方法等)。

这一直很好,正确性和覆盖率是verifiable via unit tests。但是,当前方法的缺点是每个具体子类都有一个#import来包含抽象父类的头(请参阅this headerimplementation) - 这意味着我必须导出父类标题,因此客户端代码将编译。如果有一种方法可以在标题中使用@class而不是#import,那么调用代码就不必知道或关心抽象父类。 (它也会简化并略微缩小框架的大小。)但是,当我尝试这个时:

// CHCircularBufferQueue.h
#import "CHQueue.h"
@class CHAbstractCircularBufferCollection;

@interface CHCircularBufferQueue : CHAbstractCircularBufferCollection <CHQueue>

@end

我收到此错误,即使我在.m文件中#import CHAbstractCircularBufferCollection.h

  

找不到'CHAbstractCircularBufferCollection'的接口声明,'CHCircularBufferQueue'的超类

我希望编译器知道我正在扩展的父类,但不要求客户端。有没有办法完成我想做的事情,并从我的发行版中删除不相关的标题?

PS - 这个框架主要源于学术上的好奇心,但我正在考虑通过使用类集群和私有子类进行更改以使其更像基础集合。这也可以解决这个问题,但我很好奇是否有可行的方法来做我想问的事。

2 个答案:

答案 0 :(得分:2)

如果要继承一个类,必须知道超类的@interface(因此整个超类层次结构),以便可以计算子类的ivar偏移量。

答案 1 :(得分:2)

你必须#import超级类的.h文件。正如KennyTM所指出的那样,编译器可以计算对象结构的ivar偏移量。您可以在任何Cocoa头文件中看到这一点。例如,如果您打开NSArray.h,则第一个非注释行是:

#import <Foundation/NSObject.h>

这适用于Cocoa中的每个其他类。