【问题标题】:Avoiding #import of header for abstract-only parent class避免#import 仅抽象父类的标头
【发布时间】:2010-01-12 16:23:03
【问题描述】:

我开发了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,我也会收到此错误:

找不到“CHCircularBufferQueue”超类“CHAbstractCircularBufferCollection”的接口声明

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

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

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 接受,因为您首先得到了正确答案:父类是唯一必须导入的类头。有趣的是,Modern Runtime 可以没有标头,但@bbum 说“我们还没有去那里”——这是因为大部分情况下遗留的运行时包袱。
    【解决方案2】:

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

    #import <Foundation/NSObject.h>
    

    这适用于 Cocoa 中的所有其他类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-30
      • 2017-10-01
      • 1970-01-01
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多