如何声明实例variables和方法在类实例外不可见或不可用?

我已经浏览了这个主题上的一堆post。 也许我没有碰到“那个”,有人会指着我这个方向。 问题很简单,可能有一个简单的答案。

如果你有两个ivars,比如说“public_ivar”和“private_ivar”,你应该在哪里/怎么声明它们,以便公开什么是公开的,什么是私人的,不以任何方式暴露给看头文件的人。

同样的问题在“public_method”和“private_method”的情况下。

我喜欢干净的头文件(用其他语言),只显示我想让其他人看到的方法和ivars。 你应该能够发布你的头文件,而不会遇到某人访问他们不应该的东西的危险。 你如何在目标-C中做到这一点。

例如,假设我决定需要使用ivar来跟踪各种类的方法之间的某些数据,计数器或类似的东西,这些方法都需要访问这些信息。 如果这个ivar是在@interface下的头文件中被常规声明的,那么它的存在是公开的,并且任何创build这个类的实例的人都可以使用它。 理想的情况是,这个ivar在class级执行之外根本看不到。

您可以在类扩展中声明实例variables或声明的属性。 由于在实现文件(即不是头文件)中声明了类扩展,因此检查头文件的人将不会看到它们。 例如,在头文件中:

@interface SomeClass : NSObject @end 

并在执行文件中:

 @interface SomeClass () @property (nonatomic, assign) int privateInt; @end @implementation SomeClass @synthesize privateInt; … @end 

要么

 @interface SomeClass () { int privateInt; } @end @implementation SomeClass … @end 

请注意,没有什么能阻止在运行时访问私有/类扩展实例variables(或者在类扩展中声明的属性的访问器方法)。 我已经写了一个相当详细的post,作为关于堆栈溢出的另一个问题的答案: 是否一个私人@属性创build一个@私有实例variables?

编辑:类扩展中的实例variables在WWDC 2010会话144中提供。

编辑: “使用Clang / LLVM 2.0编译器,您还可以在类扩展名中声明属性和实例variables。

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW1

使用类扩展添加到实现文件中的类。 一个类扩展基本上是一个具有一些奖金的未命名的类别:其中声明的属性可以合成,并且在其中声明的任何东西都必须在主实现中,所以编译器可以检查以确保你不会错过一个实现。 您必须在实施之前放置类扩展。 您不能直接在类扩展中添加实例variables,但可以添加属性。 当你为没有相应实例variables的属性合成访问器时,新的运行时(os x 10.5及更高版本和iOS的所有版本,我相信)会自动创build实例variables。 这意味着你不能创build你自己的访问器,除非你把实例variables放在你的头文件中。 私有方法可以毫无限制地添加到类扩展中,但是正如Anomie指出的那样,如果知道它们被称为什么,使用它们在技术上是可行的,而使用类转储则没有什么是安全的。

类扩展的示例用法:

 @interface MyClass () @property (retain) id privateIvar; @property (readwrite) id readonlyProperty; // bonus! class extensions can be used to make a property that is publicly readonly and privately readwrite - (void)privateMethod; @end @implementation MyClass @synthesize privateIvar; // the runtime will create the actual ivar, and we just access it through the property - (void)privateMethod { ... } ... 

创build“实例variables”的另一种方法是不使用标题或使用属性,而是使用关联引用 ,在运行时将数据添加到对象中。 它们在技术上与实例variables不同,其语法比较复杂。 由于他们也需要新的运行时,所以只有两个原因是你真的想要使用它们:你想在一个类中添加一个实例variables(在这个问题的范围之外),或者你需要它真的是私有的。 关联引用不会在编译的代码中创build任何方法或添加到类的定义中,因此,如果您不为其创build包装,那么在添加数据后不要求对象就不可能find它们。 查看我链接的页面底部以获得完整的使用示例。

您可以使用@private来指定ivars是私有的。 然而,没有办法使一个方法是私人的。 即使方法没有在头文件中列出,如果有人知道他们可以调用它的名称和参数。