这篇文章对OC中的变量做一下整理,主要有成员变量/实例变量、属性/属性变量、全局变量。先说一下各个变量的定义位置:
- 成员变量/实例变量:定义在@interface或@implementation语句紧随的大括号里面的变量。
- 属性/属性变量:定义在@interface部分的@property后面的变量。
- 全局变量:在@interface或@implementation语句之前的变量。
- 静态变量:在@implementation中,使用static进行说明的变量。
下面用图片说明:
通过测试,将变量的作用域列成了一张表。
其中绿色的表示在不更改声明位置或不需要调用父类方法的情况下,可以直接访问;有注明的,说明需要做额外工作。
静态变量指静态全局变量,是在全局变量声明时在前面使用static说明的全局变量。
在使用变量时,还有一些需要注意的点:
1. @implementation面向私有实现,@interface面向公有访问,类似接口。所以都是实例变量,在@interface和@implementation中声明是有差别的,子类可以访问@interface中的变量,但是不能访问@implementation中的变量。
2. 对于在@interface中声明的实例变量,在声明时还可以对作用域做进一步精确控制,就是在大括号中使用@public,@private,@protected和@package。对于@public的属性,在任何位置都可以访问,但是访问方式略有不同,需要使用 -> 指针运算符。如果不加说明,实例变量默认是@protected,也就是在本类和子类中可以访问。
3. 声明属性时,只需要使用@property声明即可让编译器自动生成getter/setter方法,getter/setter方法是“属性”的固有特性,@synthesize是为了让Xcode自动生成实例变量,当同时使用自动生成的实例变量自定义getter/setter时,@syncthesize是必须的。为了保证封装性,在@implementation部分,也会使用@synthesize将实例变量和属性关联,使用下面的方法:
1 | @synthesize var = _var; |
其中具有下划线的是实例变量,前面的是属性。这样就完成了关联,在@implementation中使用实例变量完成对属性的操作,减少和@interface部分的耦合。当然,在@implementation中也可以使用getter/setter访问属性。
4. extern是在使用位置对全局变量的声明,正因如此,编译器将extern解释为对变量的声明,所以当在定义语句中使用extern时,编译器会进行警告。使用静态全局变量时,可以不使用extern进行声明(因为只能在定义的文件中访问);同样地,在全局变量的定义文件中,也可以不使用extern。