《iOS应用程序开发方法与实践》补充内容-2.13 再谈类的声明与实现

2.13 再谈类的声明与实现

《iOS应用程序开发方法与实践》的第二章介绍了如创建类。在Objective-C中,类被分为两大部分,分别是类的外部接口(@interface部分)与内部实现(@implementation部分)。外部接口应该包含类向外界使用者提供的服务;而内部实现则应该包含实现上述服务的过程和细节,这些细节是类的使用者不需要也不应该知道的。

2.13.1 再谈类的成员变量

在教材2.4节以及本人博文“Objective-C中的类别(Category)的使用”中介绍了类扩展(即无名类别)的使用方法。类别(有名的类别)中只能添加静态或实例方法,不能添加成员变量与属性;而类扩展可以添加成员变量、属性和方法,访问级别均为私有。正因为私有访问级别,类扩展应位于类的实现文件(.m)中。

打开《iOS应用程序开发方法与实践》第二章配套代码Ch02_Class项目,其中包含了类Cat,其外部接口如下:

@interface Cat : NSObject <Pet>
{
@private
    //保存名字
    NSString* _name;
    //保存年龄
    int _age; 
}
......//省略方法与属性声明
@end
早期版本的Objective-C要求将类的成员变量编写在外部接口的成员变量区(即大括号区域)之内,如上面代码所示。这里,Cat类定义了两个私有的成员变量,分别是字符串类型的_name与整型的_age。上述代码是正确的并可以通过编译的,但是仔细想想不难发现一个问题,那就是Cat类的使用者有必要知道这两个成员变量的存在吗?答案是否定的,因此这就是早期Objective-C在定义类时的一个问题。

新版的Objective-C引入了类扩展,因此更好的方式是将成员变量放置在类扩展中。由于类扩展位于.m文件中,使用者是不知道成员变量的存在的。打开Cat.m,在Cat类的@implementation之前创建Cat类扩展,并将外部接口中的所有成员变量移至类扩展中,并去掉@private指令,代码如下:

// Cat.h
#import "Pet.h"
@interface Cat : NSObject <Pet>
//此时大括号区域没有了
......//省略方法与属性声明
@end

// Cat.m
#import "Cat.h"
@interface Cat ()
{
    //保存名字
    NSString* _name;
    //保存年龄
    int _age;
}
@end

@implementation Cat
......
@end

这样一来,外部就无法知晓类的成员变量了,起到了内部信息保护的目的。


2.13.2 再谈类的属性

类的属性允许类的使用者以安全合理的方式访问和修改成员变量的值,属性对应成员变量及其get与set方法。在Xcode 4.5及早期版本中,我们大多是在@interface中通过@property指令声明属性,然后在@implementation中通过@synthesize指令实现属性(参见《iOS应用程序开发方法与实践》2.2.4节),例如:

// Cat.h
@interface Cat : NSObject
@property (nonatomic, strong) NSString* name;
@property (nonatomic) int age; 
@end
//Cat.m
@interface Cat ()
{
    //保存名字
    NSString* _name;
    //保存年龄
    int _age;
}
@end

@implementation Cat
@synthesize name = _name, age = _age;
......
@end

上面的代码在.h头文件中通过@property声明了属性,在.m文件的类扩展部分创建了两个私有成员变量,并且通过@synthesize将name属性关联到_name,将age关联到_age,并分别生成了get与set方法。注意,如果使用了@synthesize,则无需显式定义关联的成员变量,即上面类扩展中大括号部分可以全部去掉。

//Cat.m
@interface Cat ()
@end

@implementation Cat
@synthesize name = _name, age = _age;
......
@end
另外,自iOS 6.0与Xcode 4.5后,编译器支持根据属性的声明语句自动实现属性,无需显式编写@synthesize了(终于可以松一口气了。。。)。自动实现属性会将属性关联到以属性名前面附加一个下划线为名称的成员变量,并生成对应的get与set方法。于是Cat.m进一步简化为:
//Cat.m
@interface Cat ()
@end

@implementation Cat
......
@end

另外,正如2.13.1中可以将私有成员变量定义在类扩展中一样,我们也可以定义私有属性,即仅供类内部使用的属性而不被外界使用者看到,例如我们定义一个私有属性nickname:

//Cat.m
@interface Cat ()
@property (nonatomic, strong) NSString* nickname;
@end

@implementation Cat
......
- (void)printNickname
{
    NSLog(@"My nickname is %@, please keep it confidential~", self.nickname);
}
@end
这里在类扩展中声明了私有属性nickname,那么这个属性只能在类的内部使用,外界无法访问。由于没有使用@synthesize,编译器会自动实现属性,将其对应到私有的成员变量_nickname上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值