一、目标
1、能够区别属性和实例变量
2、熟练使用属性和点语法
3、熟练掌握封装(面向对象三大特性之一)
二、属性
场景:一个类包含100个甚至更多实例变量,我们需要为每个实例变量进行赋值操作。
解决方式1:写100个设置器和100个访问器。
解决方式2:OC 2.0中定义了属性(property)的概念,属性是一组设置器和访问器,它简化了上述的操作,与类相似,属性需要声明和实现。
1、属性的声明
属性的声明:
属性的声明写在类的.h文件中
@property int age;
相当于声明了两个方法:
- (void)setAge:(int)age;
- (int)getAge;
2、属性的实现属性的实现写在类的.m文件中
@synthesize age = _age;
相当于实现了两个方法:- (void)setAge:(int)age{
_age = age;
}
- (int)getAge{
return _age;
}
3、为Person类添加三个属性Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString *name;
@property NSInteger age;
@property NSString *gender;
//添加初始化方法
- (id)initWithName:(NSString *)__name;
- (void)sayHi;
@end
Person.m#import "Person.h"
@implementation Person
@synthesize name = _name;
@synthesize age = _age;
@synthesize gender = _gender;
- (id)initWithName:(NSString *)__name{
self = [super init];
if (self != nil) {
self.name = __name;
}
return self;
}
- (void)sayHi{
NSLog(@"%@ Hello World",self.name);
}
@end
main.m#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *person = [[Person alloc]initWithName:@"hehe"];
[person sayHi];
[person setName:@"Jack"];
[person sayHi];
person.name = @"xiaoming";
[person sayHi];
return 0;
}
注意:在声明属性和实现属性的地方会有异常,这里先跳过不处理。三、属性的特性
刚才上面说的有异常,是因为我们没有为我们定义的属性设置特性。
属性也可以设置特性(attribute)主要包括三个方面:读写特性、原子性特性、setter语义特性
1、读写特性
读写属性可以通过厦门关键字进行设置:
readwrite 可读写(既有设置器也有访问器)默认
readonly 只读(只有访问器没有设置器)
getter = 方法名 指定访问器的方法名
setter = 方法名 指定设置器的方法名
2、原子性属性
原子性属性可以通过下面关键字设置:
nonatomic 非原子性,不保证多线程安全
atomic 原子性,多线程访问时较安全
3、语义属性
语义属性可以通以下关键字设置:
accign 直接赋值 适用于基本数据类型
retain 赋值时做内存优化 适用于对象类型
copy 复制一个副本 适用于特殊的对象类型
四、点语法
一旦我们有了实例变量的设置器和访问器就可以使用OC的点语法。
比如:p.age = 20; 等价于 [p setAge:20];
int age = p.age; 等价于 int age = [p getAge];
五、小结
1、属性和实例变量是不同的,前者是一组方法,后者是一个变量
2、定义属性@property 和 @synthesize
3、基本数据类型使用assign,对象类型使用ratain,实现了NSCopying协议的对象使用copy
4、点语法和[receiver message]是等价的
总结
如果只有访问器,能使用点语法吗?只有设置器呢?
术语和技巧
@synthesize age = _age;作用是setAge:以及age方法都是在操作实例变量_age,没有_age的话,编译器会帮你生成_age