@property和@synthesize以及@property增强

在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的实现

 

补充:什么是私有属性和真私有属性。

私有属性就是定义在@interface大括号中的带下划线的属性。(外部可以通过->查看,但是不能访问和修改)
真私有属性,就是定义在.m文件中没有在.h文件公布的属性(匿名延展大括号属性+括号外属性)。(外部不能查看,更不能访问和修改,只能在.m文件使用)
 
那么私有属性和真私有属性有什么不同呢?
私有属性,在.h大括号中创建出来,默认是@protectd权限,外界不能通过->来访问该属性,但是外界可以通过->查看到属性,只不过属性不能被访问和修改。但是,在.m文件中添加的匿名延展中,在大括号中添加的属性,不能通->访问。
#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"]);
}

 

真私有属性,在@implementation大括号中创建,只能被本身的.m文件调用,外界不能访问和修改,也不能通过->来访问到该属性,但可以使用kvc赋值(无论是.h大括号的私有属性,还是.m文件中的真私有属性)
#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];

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值