oc中,对象声明成员变量的几种方式,以及对应的一些扩展知识

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,setter=@(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

以上就是几种变量的声明方式,真是走马观灯,眼花缭乱。
不过在日常开发中,一半较少遇到变量作用域的问题,正常使用就好。这些各种各样的方式,还是留给有需要的人去用吧。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值