#import <Foundation/Foundation.h>
@interface Person : NSObject
{
// 1.声明成员变量
NSString *name;
NSInteger age;
}
//@property声明属性
@property (nonatomic, copy) NSString *fatherName;
@end
声明的属性默认会生成一个_类型的成员变量,同时也会生成setter/getter方法。但这只是在iOS5之后,苹果推出的一个新机制。看老代码时,经常看到一个大括号里面定义了成员变量,同时用了@property声明,而且还在@implementation中使用@synthesize方法。现在编译器会自动的生成一个实例变量_fatherName,那么在.m文件中可以直接的使用_fatherName实例变量,也可以通过属性self.fatherName.都是一样的。注意这里的self.fatherName其实是调用的fatherName属性的getter/setter方法。
其实,发生这种状况根本原因是苹果将默认编译器从GCC转换为LLVM(low level virtual machine),才不再需要为属性声明实例变量了。在没有更改之前,属性的正常写法需要成员变量+ @property + @synthesize 成员变量三个步骤。
@synthesize 还有一个作用,可以指定与属性对应的实例变量,例如@synthesize fatherName = xxx;那么self.fatherName其实是操作的实例变量xxx,而不是_fatherName了。
在实际的项目中,我们一般这么写.m文件
@synthesize fatherName;
这样写了之后,那么编译器会自动生成fatherName的实例变量,以及相应的getter和setter方法。注意:_fatherName这个实例变量是不存在的,因为自动生成的实例变量为fatherName而不是_fatherName,所以现在@synthesize的作用就相当于指定实例变量;
如果.m文件中写了@synthesize fatherName;那么生成的实例变量就是fatherName;如果没写@synthesize fatherName;那么生成的实例变量就是_fatherName。所以跟以前的用法还是有点细微的区别。
1.成员变量的作用范围:
@public:在任何地方都能直接访问对象的成员变量
@private:只能在当前类的对象方法中直接访问,如果子类要访问需要调用父类的get/set方法
@protected:可以在当前类及其子类对象方法中直接访问(系统默认下是用它来修饰的)
@package:在同一个包下就可以直接访问,比如说在同一个框架
2.注意:
无论父类是在@interface还是@implementation声明的成员变量子类都能拥有;但是子类能不能直接通过变量名来访问父类中定义的成员变量是需要看父类中定义的成员变量是由什么修饰符来修饰的。
3.默认:
在.m中成员变量的修饰符为@private.
在.h中成员变量的修饰符@protected.
@property声明属性是: 在.m中成员变量的修饰符为@private. 在.h中成员变量的修饰符@protected.