Objective c 在ObjC实现文件中声明的实例变量

Objective c 在ObjC实现文件中声明的实例变量,objective-c,automatic-ref-counting,Objective C,Automatic Ref Counting,我正在看WWDC ARC介绍视频,看到了一些我在ObjC中从未见过的东西,当时一些苹果工程师谈到了堆栈示例 以下代码用于带有ARC的堆栈示例: @implementation Stack { // instance variable declared in implementation context NSMutableArray *_array; } - (id)init { if (self = [super init]) _array = [NS

我正在看WWDC ARC介绍视频,看到了一些我在ObjC中从未见过的东西,当时一些苹果工程师谈到了堆栈示例

以下代码用于带有ARC的堆栈示例:

@implementation Stack 
{ 
    // instance variable declared in implementation context
    NSMutableArray *_array; 
}

- (id)init 
{
   if (self = [super init])
      _array = [NSMutableArray array];
   return self;
}

- (void)push:(id)x 
{
   [_array addObject:x];
}

- (id)pop 
{
   id x = [_array lastObject];
   [_array removeLastObject];
   return x;
}

@end
请注意在@implementation指令之后声明的实例变量

现在让我吃惊的是,实例变量实际上可以在实现文件中声明,而不是静态变量。我的问题如下:

  • 这是iOS 5 SDK中引入的某种新构造,还是已经存在很长时间了
  • 如果不在对象外部访问实例变量,那么在实现中声明实例变量是否是一种好的做法?它似乎比@private指令的使用更干净

这确实是一种新的语言功能,如果您必须声明IVAR(而不是简单地声明属性并让编译器为您生成IVAR),这是一种很好的做法。从理论上讲,头文件应该只公开类的公共接口;其他一切都属于实现


需要注意的一点是,实现文件ivar对于子类是不可见的,如果您已经手动生成了需要子类化的setter和getter,这有时会有点尴尬

在实现中声明IVAR无疑是目标C中的一个新构造。 您需要使用xcode4.2,并在生成设置中选择LLVM编译器。 这样做的目的是使头文件更干净。你可以在花括号里列出你的IVAR 像这个例子,

@implementation MyClass {    
  int var1;
  int var2;
}

Rahul给出的答案并不完全正确,尽管你可以用他说的编译器将变量视为静态变量的方式来定义它们。可能对于他使用它们的情况来说,这并不重要。

我不熟悉目标C,我发现在标题中声明IVAR的做法非常奇怪。这意味着在其公共头中声明对象的内部状态,这违背了封装的概念

例如,假设你拥有一台IPad。苹果不希望你打开IPad,四处窥探,弄乱里面的东西。如果他们想让你修改一些东西,IPad会有一个设置,让你可以修改

同样,我不希望其他程序员看到我的对象的IVAR。这是我的对象的内部状态。如果我希望您访问内部状态,我将为其声明属性

因此,就像在其他语言中一样,我会将ivar隐藏在implementationfile中,而不是在头文件中声明它们

在头球中宣布IVAR让我觉得非常奇怪。
这些IVAR是特定于实现的,不应该是头文件的一部分。

您有完整的,这方面的可编译示例?上面的代码应该可以用iOS 5 SDK编译。改为在类扩展中添加IVAR如何?@OscarGomez试图在扩展中声明IVAR,在当前版本的Xcode中出现了一个错误,提示“实例变量可能不放在类扩展中”。以前允许这样做吗?@Danra我在网上查了一下,似乎出于某种奇怪的原因,它只能在iOS上工作。假设我创建了一个类“a”,它只在实现文件中声明其IVAR(用于封装),但我想创建一个可变子类“MutableA”。我如何才能在一个应用程序中访问实现IVAR?注意:这些IVAR没有属性,也没有getter/setter。一位苹果工程师告诉我这项新功能,并建议我使用它。在查看nsattributetstring.h之前,有点忘记了它,但找不到IVAR。Objective-C主题“定义一个类”已相应更新,并将接口中的IVAR声明称为“历史”作为子类中的可见性-子类实现是否只使用访问器函数?@GTAE86是的,尽管我认为使用头声明仍然很常见(或者是头声明和实现声明的混合)。@SeamusCampbell:上面的代码在iOS4.0中可以工作吗?我已经与Deplyment target4.0进行了检查,它可以工作,但在运行时会导致任何问题吗?这与在扩展中声明IVAR相比如何(即
@interface MyClass(){…}
)?它还允许您不在标头中声明IVAR。您还需要符合“现代”Objective-C运行时的资格,该运行时根据在iOS上可用,以及OS X 10.5和更高版本的64位。OS X 10.5之前版本和OS X 32位版本使用传统运行时。