oc继承自c,c的变量声明方式这里就不说了,进入正题。
@interface中声明成员变量
oc最原始的变量声明,就是在@interface中声明。默认的声明方式就是隐性的@protected
@interface ClassA :NSObject
{
NSInteger oneInteger; //隐含@protected的意思
}
@end
oc中也支持继承,因此如果想声明私有变量,不允许子类访问该变量,可以 加 @private标识符
@private
NSInteger oneInteger;
如果想声明公有变量,想在对象的外部进行访问,可以这样:
@public
NSInteger oneInteger;
//访问的方式如下
classA->oneInteger = 123;
后来苹果又提供了一个新的声明标识@package,使变量只能在framework内才是public。苹果官方文档摘抄如下
@package is a new instance variable protection class, like @public and @protected. @package instance variables behave as follows:
(@package是一个新的成员变量保护域,就像@public和@protected。使用@package作用域的成员变量,有如下特征:)
@public in 32-bit;
@public in 64-bit, inside the framework that defined the class;
@private in 64-bit, outside the framework that defined the class.
(在32位系统中,@package和@public等同
在64位系统中,framework内的@package变量,可以像@public变量一样使用
在64位系统中,framework外不能访问@package变量,甚至继承framework中的类都不可以,类似@private)
@property时代
后来有一本红宝书,风靡一时,大家都看过吧,叫 《Objective-C.2.0程序设计》
在这本书中,介绍了属性声明@property以及存取器@synthesize。属性声明使得一个变量可以在对象外部进行访问,而存取器则默认生成了变量的setter和getter方法。
//头文件
@interface ClassA :NSObject
{
NSInteger oneInteger;
}
@property(nonatomic)NSInteger oneInteger;
@end
//实现文件
@implementation ClassA
@synthesize oneInteger;
@end
这样的话,想访问ClassA的变量就方便了许多
classA.oneInteger = 12; //setter方法设置变量
NSLog(@"%d", classA.oneInteger); //getter方法获取变量
如果要隐藏成员变量名,还可以给变量取别名
//头文件
@interface ClassA :NSObject
{
NSInteger oneInteger; //成员变量
}
@property(nonatomic)NSInteger propertyInteger; //别名
@end
//实现文件
@implementation ClassA
@synthesize propertyInteger = oneInteger; //别名,映射到成员变量上
@end
存取器默认生成setter和getter方法,如果有需要仍可以自定义,自定义的方法会覆盖系统生成的方法。setter和getter方法的定义规则:
//setter方法名为 set+首字母大写的变量名 ,参数类型必须是变量的类型。
- (void)setOneInteger:(NSInteger)aInt;
//getter方法名与变量同名,返回类型必须是变量的类型;
- (NSInteger)oneInteger;
声明属性时,还可以指定setter和getter的方法
@property(nonatomic,[email protected](setAnInteger:))NSInteger oneInteger;
此时,oneInteger的set方法就变成了 -(void)setAnInteger:(NSInteger)aInt;
后来苹果推出新特性,允许不声明变量,只写@property和@synthesize。
//头文件
@interface ClassA :NSObject
@property(nonatomic)NSInteger oneInteger;
@end
//实现文件
@implementation ClassA
@synthesize oneInteger;
@end
此时编译器默认帮助生成一个变量,与@property同名。即,默认生成了一个NSInteger oneInteger;
如果在不声明变量的情况下,存取器使用别名,则声明的变量名与=后面的名字相同。
@synthesize oneInteger = abc; //生成的变量为abc
除了可以不声明变量,甚至存取器都可以省略了
//头文件
@interface ClassA :NSObject
@property(nonatomic)NSInteger oneInteger;
@end
此时有所不同的是,默认生成的变量名为 下划线+属性名。即,默认生成了一个NSInteger _oneInteger;
在特殊的匿名分类Category中声明变量
oc中的分类大家都用过,分类不允许声明成员变量,可以声明属性和方法。
以ClassA为例,可以声明一个分类
@interface ClassA (Category1)
@property(nonatomic)NSInteger cateInt; //允许声明@property
- (void)cateFunc; //允许声明方法
@end
使用分类,使得隐藏@property成为可能,将Category写在.m文件中,则其他文件都无法访问到,相当于变相的@private。
但是有一个特殊的分类,不写分类名,称之为 匿名分类。匿名分类的一个重要特征,就是允许声明成员变量,且默认@private熟悉
@interface ClassA ()
{
NSInteger cateInt; //匿名分类,允许声明成员变量
}
@end
当然,可以使用@protected等标识来改变它的作用域。
在@implementation中声明变量
苹果对变量的作用域一直如此纠结,现在又推出一种新的变量声明方式,变量声明在实现文件@implementation中。这样就变成了只能在对象内使用,相当于@private。
//头文件
@interface ClassA :NSObject
@end
//实现文件
@implementation ClassA
{
NSInteger oneInteger; //相当于私有变量 @private
}
@end
以上就是几种变量的声明方式,真是走马观灯,眼花缭乱。
不过在日常开发中,一半较少遇到变量作用域的问题,正常使用就好。这些各种各样的方式,还是留给有需要的人去用吧。