点语法

一、点语法的本质是方法的调用,而不是访问成员变量(OC中访问成员变量只能使用->),当使用点语法时编译器会自动展开成相应的方法(编译器特性)。

点语法陷阱(ARC):

1)死循环

- (void)setAge:(int)age {
    self.age = age;
}

分析:self.age = age 实际为赋值调用 set 方法; 会被编译器展开成如下代码,造成了死循环!

- (void)setAge:(int)age {
    [self setAge:age];
}

正确写法:

- (void)setAge:(int)age {
    self->_age = age;
}

或:

- (void)setAge:(int)age {
    _age = age;
}

说明:age为Person类的属性,在Person.m中我们可以使用 “->”访问私有成员变量 _age;

2)死循环

- (int)age {
    return self.age;
}

此处的 self.age 实际为取值,调用 get 方法,造成死循环。展开如下:

- (int)age {
    return [self age];
}

分析:此处的self.age,是取值,则会被编译器转为 [self age];即调用了get方法,造成了死循环!

正确写法:

- (int)age {
    return self->_age;
}

或:

- (int)age {
    return _age;
}

 

二、@property 和 @synthesize 关键字(编译器指令:告诉编译器要做什么)

先说一说为什么使用 @property

// .h
@interface Person : NSObject {
    int _age;
}

- (void)setAge:(int)age;
- (int)age;

@end

// .m
@implementation Person

- (void)setAge:(int)age {
    _age = age;
}

- (int)age {
    return _age;
}

@end

以上是手动实现的 age 属性的 set/get 方法。

@property 会告诉编译器,声明 age 属性的访问器(set/get)方法,免去我们手工书写的繁琐!

示例:

// .h 声明age属性
@property (nonatomic, assign) int age; // 等同于声明了age属性set和get方法

// 访问器
- (void)setAge:(int)age;
- (int)age;

 

@synthesize 会告诉编译器,生成 age 属性(set/get)的实现!

示例(通用写法):

// 告诉编译器生成 age 属性的访问器,且在访问器里访问 _age 成员变量;如果没有 _age 成员变量,则自动生成@private的_age成员变量(私有的)
@synthesize age = _age;
// @synthesize 等同于set和get的实现,书写在@implementation……@end 之间
- (void)setAge:(int)age {
    _age = age;
}

- (int)age {
    return _age;
}

示例:

// .h
@property (nonatomic, assign) int age;
@synthesize age = _num;
分析:表示用 age 的 setget 方法,修改 _num 属性变量的值

- (void)setAge:(int)age {
    _num = age;
}

- (int)age {
    return _num;
}

示例:

// 默认会访问 age 成员变量,而不是 _age;
@synthesize age;

 

三、Xcode4.4之后,

1)@property增强版。只要:

@property (nonatomic, assign) int age;

好处:系统就会帮我们实现 age 属性的 set/get 方法。

缺点:自动生成的成员变量 _age 是私有的,子类是不能访问的。

如果让子类访问父类的 _age 成员变量,须手动实现 _age 成员变量:

// .h 
@interface Person : NSObject {
    int _age;
}
@property (nonatomic, assign) int age;
@end
// Man 继承自 Person
@implementation Man
- (void)test {
    // 父类Person,存在 _age 成员属性,则子类就可以使用 _age数形变量
    NSLog(@"%d", _age);
}
@end

 

2)@property增强下重写 set/get 方法

1)如果手动实现了set方法,那么编译器就只生成get方法和对应的成员变量;
2)如果手动实现了get方法,那么编译器就只生成set方法和对应的成员变量;
3)如果set和get方法都是手动实现的,那么编译器将不会生成成员变量,且报错(Use  of undeclared identifier ‘_age’)。

若需要重写 set/get 方法,正确写法:

@synthesize age = _age;

- (void)setAge:(int)age {
    _age = age;
}

- (int)age {
    return _age;
}

尊重作者劳动成果,转载请注明: 【kingdev】

posted @ 2015-04-25 13:09  Kingdev  阅读(229)  评论(0编辑  收藏  举报