为什么在Objective-C的头文件中定义了实例变量

far*_*adf 6 objective-c

我可以理解在头文件的@interface中定义函数,但为什么实例变量?实例变量不应该是私有的,只能通过消息访问吗?

Die*_*Epp 8

原因是它可以计算子类的变量偏移量.

@interface Bird : NSObject {
    int wingspan;
}
@end
@interface Penguin : Bird {
    NSPoint nestLocation;
    Penguin *mate;
}
@end
Run Code Online (Sandbox Code Playgroud)

在不知道"Bird"类的结构的情况下,"Penguin"类无法从结构的开头计算其字段的偏移量.企鹅结构看起来像这样:

struct Penguin {
    int refcount; // from NSObject
    int wingspan; // from Bird
    NSPoint nestLocation; // from Penguin
    Penguin *mate; // from Penguin
}
Run Code Online (Sandbox Code Playgroud)

这有副作用:如果更改库中类的大小,则会中断链接到该库的应用程序中的所有子类.新属性解决此问题.


Nic*_*mas 6

虽然它们是在头文件中声明的,但是Objective-C中的所有实例变量都默认具有@protected访问权限.这意味着变量可以在声明它的类和从该类继承的任何类中访问.

以下是Apple关于定义Objective-C类的文档:定义类

请注意标题为"实例变量的范围"的部分.


Sij*_*der 6

我认为这是一个技术问题.如果我理解正确,Objective-C类只是一个奇特的C结构.对于要使用的结构,必须知道它的大小.(就像sizeof()如何工作)


sic*_*ckp 5

如果有人遇到这个问题 - 从使用LLVM编译器的XCode 4.2开始,您可以使用以下括号表示法在@implementation中声明实例变量:


@interface SomeClass : NSObject
@end

@implementation SomeClass {
  NSString *myInstanceVariable_;
}

- (void)moreMethods {}
@end
Run Code Online (Sandbox Code Playgroud)

实例变量通常不应该是声明为public interface的类的一部分 - 它们是实现细节.

但是,请确认您的括号内定义的实例变量,否则你会被限定已没有关系对象实例的全局变量:


@implementation SomeClass
  NSString *whoopsGlobalVariable_;

- (void)moreMethods {}

@end
Run Code Online (Sandbox Code Playgroud)