在OC中我们写一个类:
a.首先要给类写属性
b.再声明属性的getter和setter方法
c.再实现getter和setter方法的实现
就例如创建一个Person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
int _age;
}
- (void)setName:(NSString *)name;
- (NSStirng *)name;
- (void)setAge:(int)age;
- (int)age;
@implementation Person
- (void)setName:(NSString *)name
{
_name = name;
}
- (NSString *)name
{
return _name;
}
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}
这样创建一个类,非常的麻烦,所以苹果出了一个@property.就是创建类的属性的时候,直接使用@property 属性名,去掉下划线。然后系统就会帮你自动生成@property属性的setter和getter方法的声明,但是属性还是需要自己创建
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
NSString *_name;
int _age;
}
@property name;
@property age;
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property name;
那么@property name这句代码究竟帮我们做了什么:这句代码相当于生成了以下代码
-(void)setName:(NSString *)name;
-(NSString *)name;
那么@property只是帮我们生成属性的getter方法和setter方法而已,那么实现怎么办。
就是使用@synthesize。只要使用@synthesize,在.m文件中就会生成对应的setter和getter方法的实现
注意:setter和getter方法的实现,只是给属性简单赋值而已,没有什么逻辑验证。
@implementation Person
@synthesize name;
@synthesize age;
@synthesize name这句代码相当于生成了以下代码
@implementation Person
{
NSString *name;
Int age;
}
- (void)setName:(NSString *)name
{
name = name;
}
- (NSString *)name
{
return name;
}
- (void)setAge:(int)age
{
age = age;
}
- (int)age
{
return age;
}
需要注意的是:
使用@synthesize的确会生成对应属性的setter和getter方法,但是@synthesize同样会生成一个去掉下滑线的与@property对应的真私有属性。而且,setter和getter方法的实现的操作都是在@synthesize自动生成的真私有属性上,那么就是在.h文件中声明的下划线属性完全没用了,直接可以删除掉了。但是这种做法不建议。因为@synthesize自动生成的真私有属性不符合命名规范。那么,我们应该怎么使用@synthesize呢。
@synthesize name = _name;
@synthesize age = _age;
这样写
1.不会再去生成真私有属性。
2.直接生成setter和getter方法的实现
@property增强
@property只是生成 getter 和 setter 的声明
@synthesize只是生成 getter 和 setter 的实现
这种写法是Xcode4.4之前的写法,从Xcode4.4以后。Xcode对@property进行了增强
@property增强
只需要写一个@property 编译器就会自动
1.生成 私有属性(带下划线属性)
2.生成属性的getter setter的声明
3.生成属性的getter setter的实现
补充:什么是私有属性和真私有属性。
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface Human : NSObject
{
NSString *_sex;
NSString *_school;
NSString *_name;
}
@end
NS_ASSUME_NONNULL_END
- (void)test2 {
Human *people = [[Human alloc] init];
[people setValue:@"xiaoming" forKey:@"name"];
NSLog(@"people.name = %@",[people valueForKey:@"name"]);
[people setValue:@"清华大学" forKey:@"school"];
NSLog(@"people.school = %@",[people valueForKey:@"school"]);
[people setValue:@"male" forKey:@"sex"];
NSLog(@"people.school = %@",[people valueForKey:@"sex"]);
}
#import "Human.h"
@interface Human ()
{
NSString *_age;
}
@end
static UIViewController *humanFace;
@implementation Human
@end
- (void)test2 {
Human *people = [[Human alloc] init];
[people setValue:@"xiaoming" forKey:@"name"];
NSLog(@"people.name = %@",[people valueForKey:@"name"]);
[people setValue:@"清华大学" forKey:@"school"];
NSLog(@"people.school = %@",[people valueForKey:@"school"]);
[people setValue:@"male" forKey:@"sex"];
NSLog(@"people.school = %@",[people valueForKey:@"sex"]);
[people setValue:@"18" forKey:@"age"];
NSLog(@"people.age = %@",[people valueForKey:@"age"]);
}
点语法
原始创建一个类,属性都定义在@interface的大阔号中,定义在这里的属性也叫实例变量。默认访问权限是@protectd,外界不能访问。只有把权限修改为@public,外界才能通过->来访问和修改该属性。
但是使用->来访问属性,又太过于麻烦。因此出现了点语法。就是类如Person类的一个对象p1有一个name属性,通过p1->name 和p1.name 结果是一样的。
那么点语法的原理是什么呢?
p1.age = 18;
这句话的本质并不是把18直接赋值给p1对象的_age属性.
点语法在编译器编译的时候.其实会将点语法转换为调用setter、getter的代码.
1). 当使用点语法赋值的时候.这个时候编译器会将点语法转换为调用setter方法的代码.
对象名.去掉下划线的属性名 =数据;
转换为:
[对象名 set去掉下划线的属性名首字母大写:数据];
p1.age = 10;
[p1 setAge:10];
2).当使用点语法取值的时候.这个时候编译器会将点语法转换为调用getter方法的代码.
对象名.去掉下划线的属性名;
转换为:
[对象名 去掉下划线的属性名];
int age = p1.age;
int age = [p1 age];