2

我已经编写Objective C 将近一年了,我从来没有机会将接口(.h)用于其他目的,而不是声明您可以在实现( .m)中找到的几乎相同的类结构。

由于我来自其他没有Objective C接口之类的语言,我想知道我是否缺少一些或几种用途,或者这只是这种特定语言可能从其前身继承的约定。

谢谢!

4

5 回答 5

5

您的接口是该类的公共 API。任何未在接口中声明的东西都不能从类外部访问。如果您更多地考虑 C++ 或 Java,则 .m 文件中的所有内容(未在 .h 中的 @interface 中声明)都是私有的。这就是为什么在 Objective-C 中你不会经常看到它们的关键字 @private、@public 或 @protected。

无论您在界面中放置什么,都是您打算让您的班级用户使用的东西,仅此而已。这遵循最小特权原则。

您还可以将 @interface 视为您的课程的文档。

于 2012-06-01T19:33:29.533 回答
1

除了声明几乎可以在实现 (.m) 中找到的类结构之外,我从来没有机会将接口 (.h) 用于其他目的。

该接口是该类的公开声明的接口。实现是它尊重该接口的方式。那么一个简单的例子:

@interface Accumulator: NSObject

- (void)addAmount:(NSUInteger)amount;

@property (nonatomic, assign, readonly) NSUInteger currentTotal;

@end

和:

@implementation Accumulator
{
    NSUInteger currentTotal; // an instance variable; we don't want to publish
                             // these because they're nothing to do with the
                             // interface we implement. Object orientation means 
                             // not thinking about implementations beyond
                             // your own.
}

@synthesize currentTotal;

- (void)addAmount:(NSUInteger)amount
{
     currentTotal += amount;
}

@end

因此,作为一般准则,您没有放入 @interface 的内容包括:

  • 实例变量;
  • 不适合外用的方法;
  • 对您依赖的其他类的引用,但依赖于您的人不需要知道。
于 2012-06-01T19:42:13.723 回答
0

接口文件类似于 C 和 C++ 中使用的头文件,仅在 Objective C 中,您还可以声明诸如属性协议之类的好东西(对于需要确认对象接口期望的委托之类的东西非常有用传递消息)。

您的对象的接口文件可以包含在其他对象的实现 (.m) 文件中,这样其他对象的实现就可以访问您刚刚实例化(创建)的对象的方法和属性。

于 2012-06-01T19:30:59.530 回答
0

它继承自 C,其中您有定义接口的标头和包含实现的源文件。这确实意味着一些双重输入。

例如,Java 摒弃了这种两个文件的方法,并有一个包含所有内容的文件。它没有 C 的编译和链接阶段,这是标题的部分原因。

标头方法的一个方面是,使用专有代码,您可以将您的标头连同已编译的二进制文件一起提供给某人,他们可以链接到并调用您的 API。这就是微软对 Win32 API 所做的事情,或者苹果对他们的 SDK 和操作系统所做的事情。

另请参阅为什么在 C++ 中有头文件和 .cpp 文件?

于 2012-06-01T20:06:32.407 回答
0

扩展已经说过的内容:基于 C 的语言编译器需要对 .c/.cpp/.m 文件中的单词有一定的了解,然后才能开始链接外部库或目标文件。该信息告诉编译器诸如返回类型和函数和方法的参数的数量和类型,以及类中的实例变量和方法。

如果您实际上将整个 .c/.cpp/.m 文件包含在使用其功能的文件中,那么您最终会遇到一个问题,即链接器具有不知道如何处理的重复代码;因此,头文件仅列出了他们实际需要了解的有关接口的内容,而不是实现。

C 和 Objective-C 实际上允许您省略各种接口信息,但是如果他们看到提到的函数或方法的标题没有阅读,他们就会做出(通常是不正确的)假设。例如,一个未知的函数名将被正确识别,但编译器将假定它返回一个 int;我的记忆对如何处理参数有点模糊,但是如果您传递的参数与最终链接到的已实现函数中的参数不兼容,它可能不会抱怨。因此编译器无法进行大量检查像 C 这样的静态语言擅长。

于 2012-06-01T20:35:30.510 回答