OC:属性、点语法、KVC

 //属性的属性

属性定义在一个 .h文件里,在这个.h文件里可以定义实例变量(就是这个类的特征),也可以通过   @protery(属性约束关键字) 属性名字类型 属性名 来定义一些属性,在property里面重置setter或者getter的方法名(例如:@property(readwrite,setter=haha:,getter=dedaomingnzi) NSString *name;)属性的约束有:读写约束(readonly、readwrite)原子约束(atomic)非原子约束

也可以在.m文件里定义当前类的私有的实例变量和私有方法(私有方法在声明的时候也在.m文件里声明,如果在.h文件里声明,那就是能够提供给外部接口的方法了)这就是一个类的延展(Extension);如果一个我们看不到源代码的类,我们需要他的一些方法的实现,但是该类没有实现,那就建立一个分类 ,注意分类只能仅仅是添加类的方法,category;

/*

 1.读写特性(写在 property 关键字后面的 括号内 如果不设置的话,那就是默认的readwrite

 readonly(只能去读(获取值)不能写,只有getter方法,只能获取值,不能写)

 readwrite(默认的特性  既可以读又可以写,相当于他有gettersetter方法,可以访问( 值)也可以赋值)

 setter= 的用法:他是设置 setter 方法的名字 例如:@property(readwrite,setter = haha:) NSString *name;我们在使用的时候,直接  [对象  haha:消息];

 getter= 设置getter的方法名字,也就是修改 getter 方法的名字

 

 2.原子特性

 atomic  原子特性

 nonatomic  非原子特性

 原子特性 非原子特性 的区别:在我们用setter getter 方法的时候,系统默认的是原子特性,原子特性是保护我们的线程安全(多加了个上锁 开锁的过程)好处:保护属性的安全 坏处:占用系统资源

 非原子特性:没有做线程处理,(只是简单的生成setter getter 方法)(苹果推荐使用的特性)

 线程:就是同时的做多件事

 

 3.语义特性

 assign (系统默认的特性)通常使用于基本类型 NSInterger,CGFloat,在取值与值的时候,只是简单的取值与赋值操作(就是里面自己写了 _name = name 的方法)

 retain 通常使用于 所有的对象类型 setter getter 方法就会自动生成内存优化的的代码

 copy   通常适用于对象类型,服从NSCoping 协议的对象类型才会使用 例如 NSString

 **/

 

什么是KVC

//KVC 就是三个单词的简写 key-value-coding)键值编码

        //为实例变量赋值的另一种机制,是一种间接访问对象的实例变量的机制

        Person * per = [[Person alloc]init];

        //在外部无法访问受保护的实例变量,也没用定义setter getter 这时候可以通过KVC

    //setValue:forKey:间接的给实例变量赋值 取值就是[对象 valueForKey:@“key”];

        //赋值过程

        //1.系统先检查有没有name这个实例变量

        //2.如果没有,检查有没有同名的带有下滑线的实例变量,_name.如果找到的话,就为他赋值

        //3.如果还没有的话就准备crash,他就会自动的调用一个方法,setValue:forUndefinedKey:这个方法

 

[per setValue:@"Niujianwei" forKey:@"na"];

        [per setValue:@"" forKey:@"gender"];

        [per setValue:@"Niuni" forKey:@"id"];

        [per setValue:@"sd" forKey:@"name1"];

        NSLog(@"%@",[per valueForKey:@"na"]);

        //一般通过KVC方法我们一般都要重写 setValue:forUndefinedKey valueForUndefinedKey 两个方法

        NSLog(@"%@",per);

        

        //有时候我们为了避免出错 id 改为 ID 因为 id 可能代表所有类型

       // NSString * ID

        //有时候通过间接的找不到id 就找 _id 再找不到 就走报错的处理路线(注意报错的路线也可以给某个变量赋值)

        

        //对应的取值过程

        //1.先检查有没有 name 这个实例变量

        //2.如果没有,检查有没有和他同名的带有下划线的实例变量 _name ,有的话就直接取值

        //3.如果没有的话,直接走我们的自动调用valueForUndefinedKey:方法

  

        //下面方法也是给实例变量赋值

      // per setValue:<#(id)#> forKeyPath:<#(NSString *)#>

        Phone * phone = [[Phone alloc]init];

        [phone setValue:@"iphone" forKey:@"brand"];//间接为手机赋值

        [per setValue:phone forKeyPath:@"phone"];

        NSLog(@"%@",[per valueForKey:@"phone"]);

        NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);//通过路径

        [per setValue:@"小米手机" forKeyPath:@"phone.brand"];

         NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);

 setValue: forKey    setValue: forKeyPath:


 

这段代码有什么问题吗:
@implementation Person
- (void)setAge:(int)newAge {
self.age = newAge;//点语法用在”=“的左边,就是setter 方法,self是调用当前setter 方法的对象,这样就导致了死循环,所以不能这样使用哦
}
@end


什么是Protocol?什么是代理?写一个委托的interface?委托的property声明用什么属性?为什么?
协议提供了一组方法,但是并不负责实现,如果一个类遵循了某个协议,并且实现了协议里面的方法,那么我们称这个类就是遵循了某个协议的代理。属性的声明使用assign,防止出现循环引用的问题。
分别描述类别(categories)和延展(extensions)是什么?以及两者的区别?继承和类别在实现中有何区别?为什么Category只能为对象添加方法,却不能添加成员变量?
category类目:在不知道源码的情况下为一个类扩展方法,extension:为一个类声明私有方法和变量。
继承是创建了一个新的类,而类别只是对类的一个扩展,还是之前的类。
类目的作用就是为已知的类添加方法。

KVC键值编码,可以直接通过字符串的名字(key)来间接访问属性的机制,而不是通过调用getter和setter方法访问。

对应代码:

//
//  main.m

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Phone.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
     //KVC 就是三个单词的简写 (key-value-coding)键值编码
        //为实例变量赋值的另一种机制,是一种间接访问对象的实例变量的机制
        Person * per = [[Person alloc]init];
        //在外部无法访问受保护的实例变量,也没用定义setter getter 这时候可以通过KVC
    //setValue:forKey:间接的给实例变量赋值
        //赋值过程
        //1.系统先检查有没有name这个实例变量
        //2.如果没有,检查有没有同名的带有下滑线的实例变量,_name.如果找到的话,就为他赋值
        //3.如果还没有的话就准备crash,他就会自动的调用一个方法,setValue:forUndefinedKey:这个方法
        [per setValue:@"Niujianwei" forKey:@"na"];
        [per setValue:@"" forKey:@"gender"];
        [per setValue:@"Niuni" forKey:@"id"];
        [per setValue:@"sd" forKey:@"name1"];
        NSLog(@"%@",[per valueForKey:@"na"]);
        //一般通过KVC方法我们一般都要重写 setValue:forUndefinedKey 和 valueForUndefinedKey 两个方法
        NSLog(@"%@",per);
        
        //有时候我们为了避免出错 吧 id 改为 ID 因为 id 可能代表所有类型
       // NSString * ID
        //有时候通过间接的找不到id 就找 _id 再找不到 就走报错的处理路线(注意报错的路线也可以给某个变量赋值)
        
        //对应的取值过程
        //1.先检查有没有 name 这个实例变量
        //2.如果没有,检查有没有和他同名的带有下划线的实例变量 _name ,有的话就直接取值
        //3.如果没有的话,直接走我们的自动调用valueForUndefinedKey:方法
        
        //下面方法也是给实例变量赋值
      // per setValue:<#(id)#> forKeyPath:(NSString *)
        Phone * phone = [[Phone alloc]init];
        //为phone的实例变量brand赋值
        [phone setValue:@"iphone" forKey:@"brand"];
        //通过路径:间接为手机赋值
        [per setValue:phone forKeyPath:@"phone"];
        NSLog(@"%@",[per valueForKey:@"phone"]);
        NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);//通过路径
        //通过路径:为per的实例变量phone的实例变量brand赋值
        [per setValue:@"小米手机" forKeyPath:@"phone.brand"];
         NSLog(@"%@",[per valueForKeyPath:@"phone.brand"]);
     // per setValuesForKeysWithDictionary:<#(NSDictionary *)#>
        
    }
    return 0;
}
View Code  main.m文件
//
//  Person.h

#import <Foundation/Foundation.h>
#import "Phone.h"

@interface Person : NSObject
{
    NSString *_name;
    NSString *_gender;
    NSString *_ID;
    Phone * phone;
}
-(id)description;
@end
View Code  Person.h文件
//
//  Person.m
//
#import "Person.h"

@implementation Person
-(id)description{
    return [[NSString alloc]initWithFormat:@"%@ %@ ",_name,_gender];
}
//如果 key 不存在的时候,要崩溃的时候,就执行此方法,通常用于错误的处理
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"---undefined  key-----");
    if ([key isEqualToString:@"name1"]) {
        _name = @"无名";
    }
    //有时候我们为了避免出错 吧 id 改为 ID 因为 id 可能代表所有类型
    // NSString * ID
    if ([key isEqualToString:@"id"]) {
        _ID = value;//把key 对应的 value 赋值给 ID
    }
}
//如果 key 不存在就会走这个方法 valueForUndefinedKey  有返回值
- (id)valueForUndefinedKey:(NSString *)key{
    //这里一般用作错误处理
    if ([key isEqualToString:@"na"]) {
        return @"不存在";
    }
    return nil;
}

@end
View Code  Person.m文件
//
//  Phone.h

#import <Foundation/Foundation.h>

@interface Phone : NSObject
{
    NSString *_brand;
}

@end
View Code  phone.h文件
//
//  Phone.m

#import "Phone.h"

@implementation Phone

@end
View Code  phone.m文件

为什么在定义属性的时候,定义一个

@property(readwrite,setter=haha:,getter=dedaomingnzi,copy) NSString *name; 

代码:

 1 //
 2 //  main.m
 3 //  Property

 9 #import <Foundation/Foundation.h>
10 #import "Person.h"
11 #import "Phone.h"
12 #import "Stuednt.h"
13 #import "GrilFrinend.h"
14 
15 int main(int argc, const char * argv[]) {
16     @autoreleasepool {
17         // insert code here...
18         NSLog(@"Hello, World!");
19         Person * per = [[Person alloc]init];
20 //        [per haha:@"牛建伟"];//属性里面写成 readonly
21         //如果不给stter重新命名的话,那这里就是[per setName:@"牛建伟"]
22         NSLog(@"%@",[per dedaomingnzi]);//这里修改了getter 方法名
23         
24         //点语法(把实例变量定义成属性之后)
25         //在等号的左边就是setter 方法 在等号的右边就是 getter 方法
26         //取值  对应的是 getter 方法
27         ;//[per dedaomingnzi];
28         NSLog(@"%@  %ld  %@",per.dedaomingnzi,per.age,per.gender);
29 //        per.age;   //[per age];
30 //        per.gender;//[per gender];
31         //赋值  对应的是setter 方法
32         per.age = 23;
33         per.gender = @"woman";
34         per.name = @"xinmingzi";
35         
36         //创建一个Student 类 有四个属性 初始化方法  以及便利构造器方法
37         Stuednt * stu = [[Stuednt alloc]initWithName:@"十一" gender:@"man" age:23 hobby:@"flootball"];
38         NSLog(@"%@",[stu description]);
39         Phone * phone = [[Phone alloc]initWithBrand:@"苹果6"];
40         stu.phone = phone;
41         
42         //@synthesize 查阅  KVC
43         
44     }
45     return 0;
46 }
View Code  main.m文件
 1 //
 2 //  Person.h
 3 //  Property

 9 #import <Foundation/Foundation.h>
10 
11 @interface Person : NSObject
12 {
13 //    NSString *_name;
14 //    NSString *_gender;
15 //    NSInteger _age;
16 }
17 //属性 作用:1.自动生成(已经设定的实例变量)setter getter 包括声明和实现的部分,自动生成 _属性  2.如果没有定义实例变量就会自动生成实例变量(实例变量就是 _属性名)
18 //        属性的类型  属性名
19 @property(readwrite,setter=haha:,getter=dedaomingnzi,copy) NSString *name;
20 @property(atomic,copy) NSString *gender;
21 @property(readwrite,assign)NSInteger age;
22 //属性的属性
23 /*
24  1.读写特性(写在 property 关键字后面的 括号内 如果不设置的话,那就是默认的readwrite)
25  readonly(只能去读(获取值)不能写,只有getter方法,只能获取值,不能写)
26  readwrite(默认的特性  既可以读又可以写,相当于他有getter和setter方法,可以访问(取值)也可以赋值)
27  setter= 的用法:他是设置 setter 方法的名字 例如:@property(readwrite,setter = haha:) NSString *name;我们在使用的时候,直接  [对象  haha:消息];
28  getter= 设置getter的方法名字,也就是修改 getter 方法的名字
29  
30  2.原子特性
31  atomic  原子特性(加了一个线程锁)
32  nonatomic  非原子特性
33  原子特性 与 非原子特性 的区别:在我们用setter getter 方法的时候,系统默认的是原子特性,原子特性是保护我们的线程安全(多加了个上锁 开锁的过程)好处:保护属性的安全 坏处:占用系统资源
34  非原子特性:没有做线程处理,(只是简单的生成setter 和 getter 方法)(苹果推荐使用的特性)
35  线程:就是同时的做多件事
36  
37  3.语义特性
38  assign (系统默认的特性)通常使用于基本类型 NSInterger,CGFloat,在取值与赋值的时候,只是简单的取值与赋值操作(就是里面自己写了 _name = name 的方法)
39  retain 通常使用于 所有的对象类型 setter getter 方法就会自动生成内存优化的的代码
40  copy   通常适用于对象类型,服从NSCoping 协议的对象类型才会使用 例如 NSString
41  
42  **/
43 
44 //初始化
45 - (id)initWithName:(NSString *)name
46             gender:(NSString *)gender
47                age:(NSInteger)age;
48 //
49 
50 //便利构造器
51 @end
View Code  Person.h文件
 1 //
 2 //  Person.m
 3 //  Property

 9 #import "Person.h"
10 
11 @implementation Person
12 
13 //初始化
14 - (id)initWithName:(NSString *)name
15             gender:(NSString *)gender
16                age:(NSInteger)age{
17     self = [self init];
18     if (self) {
19 //        _name = name;//在定义 @protery之后自动生名的
20 //        _gender = gender;
21 //        _age = age;
22         self.name = name;//在定义的时候一般都定义了是copy retain方法,所以在后面使用的时候一般都用点语法,这样可以在使用的时候就优化
23         self.age = age;
24         self.gender = gender;
25     }
26     return self;
27 }
28 
29         //属性的实现     name = _name 的含义:属性name 的setter 和 getter 方法在操作_name实例变量的时候,等号的右边可以随意写,但是系统的机制会先检查,.h中有没有对应的名称的实例变量,如果没有就自动生成一个,生成的默认是一个私有的实例变量
30          //在IOS6.0之后属性可以不写,编译器会自动生成对应方法的实现,操作的实例变量是跟属性同名的 _属性名 的实例变量
31 @synthesize name = _name;
32 
33 
34 //内存管理两种 1.垃圾回收机制 2.引用计数机制
35 - (void)setName:(NSString *)name{
36     if (_name != name) {//判断
37 //        内存方面的三大问题:野指针、过度释放、内存泄露
38           [_name release];
39           _name = [name retain];
40 
41     }
42 }
43 //经过内存优化的getter方法 (了解)
44 - (NSString *)name{
45     return  [[_name retain]autorelease];;
46 }
47 
48 @end
View Code  Person.m文件
 1 //
 2 //  Stuednt.h
 3 //  Property
 4 
 9 #import <Foundation/Foundation.h>
10 @class Phone;
11 
12 @interface Stuednt : NSObject
13 @property (nonatomic,readwrite,copy)NSString * name;//如果这里定义的时候加了一个_则对应生成的实例变量的时候就会有两个_,默认生成的属性名是 _属性
14 @property (nonatomic,readwrite,copy)NSString *gender;
15 @property (nonatomic,readwrite,assign)NSInteger age;
16 @property (nonatomic,readwrite,copy)NSString *hobby;
17 @property (nonatomic,retain)Phone * phone;
18 
19 //初始化
20 - (id)initWithName:(NSString *)name
21               gender:(NSString *)gender
22                  age:(NSInteger)age
23               hobby:(NSString *)hobby;
24 //便利构造器
25 + (id)initWithName:(NSString *)name
26             gender:(NSString *)gender
27                age:(NSInteger)age
28             hobby:(NSString *)hobby;
29 -(NSString *)description;
30 @end
View Code  Student.h文件
 1 //
 2 //  Stuednt.m
 3 //  Property
 4 
 9 #import "Stuednt.h"
10 #import "Phone.h"
11 
12 @implementation Stuednt
13 //初始化
14 - (id)initWithName:(NSString *)name
15               gender:(NSString *)gender
16                  age:(NSInteger)age
17               hobby:(NSString *)hobby{
18     self = [self init];
19     if (self) {
20         self.name = name;
21         self.gender = gender;
22         self.age = age;
23         self.hobby = hobby;
24     }
25     return self;
26 }
27 //便利构造器
28 + (id)initWithName:(NSString *)name
29             gender:(NSString *)gender
30                age:(NSInteger)age
31             hobby:(NSString *)hobby{
32     Stuednt * stu = [[Stuednt alloc]initWithName:name gender:gender age:age hobby:hobby];
33     return stu;
34 }
35 //重写  description 方法,返回当通过%@打印该对象类型的时候,想在控制台输出的内容
36 -(NSString *)description{
37 //    return [[NSString alloc]initWithFormat:@"name:%@  gender:%@ age:%ld hobby:%@",_name,_gender,_age,_hobby];
38     return [[NSString alloc]initWithFormat:@"name:%@  gender:%@ age:%ld hobby:%@",self.name,self.gender,self.age,self.hobby];//这里最好用点语法,因为点语法是一个setter getter
39 }
40 @synthesize name = _name;
41 //getter方法内部的实现
42 - (NSString *)name{
43     return [[_name copy]autorelease];//稍后对象引用的计数器自动减1
44 }
45 //getter方法内部实现
46 -(Phone *)phone{
47     return [[_phone retain]autorelease];
48 }
49 //语义属性为 copy 的对象的 setter 方法的内部实现
50 -(void)setName:(NSString *)name{
51     if (_name!= name) {
52         [_name release];//立即让该对象的引用计数器减1
53         _name = [[name copy]autorelease];
54     }
55 }
56 //注意我们已经吧内存机制设定为手动管理模式
57 @synthesize phone = _phone;
58 //语义的对属性为 retain 的对象的 setter 方法的内部实现
59 - (void)setPhone:(Phone *)phone{
60     if (_phone) {
61         [_phone release];
62         _phone = [[phone copy]autorelease];
63     }
64 }
65 @end
View Code  Student.m文件
 1 //
 2 //  GrilFrinend.h
 3 //  Property
 4
 9 #import "Person.h"
10 @class  Phone;
11 
12 @interface GrilFrinend : Person
13 @property(nonatomic,copy)NSString * address;
14 @property(nonatomic,assign)CGFloat height;
15 @property(nonatomic,retain)Phone *phone;
16 
17 - (id)initWithBrand:(NSString *)brand;
18 @end
View Code GrilFriend.h文件
 1 //
 2 //  GrilFrinend.m
 3 //  Property
 4 
 9 #import "GrilFrinend.h"
10 #import "Phone.h"
11 
12 @implementation GrilFrinend
13 @synthesize name = _ns;
14 //属性的实现     name = _name 的含义:属性name 的setter 和 getter 方法在操作_name实例变量的时候,等号的右边可以随意写,但是系统的机制会先检查,.h中有没有对应的名称的实例变量,如果没有就自动生成一个,生成的默认是一个私有的实例变量
15 //在IOS6.0之后属性可以不写,编译器会自动生成对应方法的实现,操作的实例变量是跟属性同名的 _属性名 的实例变量
16 - (id)initWithBrand:(NSString *)brand{
17     self = [self initWithName:@"晓红" gender:@"" age:24];
18     if (self) {
19         _ns = @"张晓红";
20     }
21     return self;
22 }
23 
24 @end
View Code GrilFriend.m文件
 1 //
 2 //  Phone.h
 3 //  Property
 4 //
 9 #import <Foundation/Foundation.h>
10 
11 @interface Phone : NSObject
12 @property(nonatomic,copy)NSString *brand;//品牌
13 - (id)initWithBrand:(NSString *)brand;//品牌初始化
14 @end
View Code  phone.h文件
 1 //
 2 //  Phone.m
 3 //  Property
 4 //

 9 #import "Phone.h"
10 
11 @implementation Phone
12 - (id)initWithBrand:(NSString *)brand{
13     self = [self init];
14     if (self) {
15         self.brand = brand;
16     }
17     return self;
18 }//品牌初始化
19 @end
View Code  phone.m文件

代码:

 1 //
 2 //  main.m
 3 //  Even
 4
 9 #import <Foundation/Foundation.h>
10 #import "Person.h"
11 #import "Student.h"
12 
13 int main(int argc, const char * argv[]) {
14     @autoreleasepool {
15         // insert code here...
16         NSLog(@"Hello, World!");
17         Person * per = [[Person alloc]initWithName:@"牛建伟" gender:@"" age:23 address:@"南阳市镇平人"];
18         NSLog(@"1111+++++%@",per);
19         Student * stu = [[Student alloc]initWithName:@"牛行建" gender:@"" age:23 address:@"南阳西峡" stunum:@"201207082437" school:@"中原工学院"];
20         NSLog(@"%@",stu.name);
21         NSLog(@"name = %@  gender = %@   age= %ld address = %@   stunumber = %@  school = %@",stu.name,stu.gender,stu.age,stu.address,stu.stunum,stu.school);
22         NSLog(@"%@",stu);
23     }
24     return 0;
25 }
View Code  main.m文件
 1 //
 2 //  Person.h
 3 //  Even
 4 //
 5 
 9 #import <Foundation/Foundation.h>
10 
11 @interface Person : NSObject
12 
13 @property(nonatomic,copy,readwrite)NSString *name;
14 @property(nonatomic,copy,readwrite)NSString *gender;
15 @property(nonatomic,assign,readwrite)NSInteger age;
16 @property(nonatomic,copy,readwrite)NSString *address;
17 //初始化
18 - (id)initWithName:(NSString *)name
19             gender:(NSString *)gender
20                age:(NSInteger)age
21            address:(NSString *)address;
22 //便利构造器
23 + (Person *)initWithName:(NSString *)name
24                   gender:(NSString *)gender
25                      age:(NSInteger)age
26                  address:(NSString *)address;
27 -(NSString *)description;
28 @end
View Code  Person.h文件
 1 //
 2 //  Person.m
 3 //  Even
 4
 9 #import "Person.h"
10 
11 @implementation Person
12 @synthesize name = _namename;
13 @synthesize gender = _gendergender;
14 @synthesize age = _ageagea;
15 @synthesize address = _addressadress;
16 
17 //初始化
18 - (id)initWithName:(NSString *)name
19             gender:(NSString *)gender
20                age:(NSInteger)age
21            address:(NSString *)address{
22     self = [self init];
23     if (self) {
24         NSString * strr = @"蓝欧学员:";
25         self.name = name;
26         self.name = [strr stringByAppendingString:name];
27         self.gender = gender;
28         self.age = age;
29         NSString * str = @"中国华人民共和国河南省";
30         self.address = address;
31         self.address = [str stringByAppendingString:address];
32     }
33     return self;
34 }
35 //重写setter getter
36 -(void)setName:(NSString *)name{
37     if (_namename != name) {
38         [_gendergender release];
39         NSLog(@"重写setter getter方法");
40         _namename = [[name retain]autorelease];
41     }
42 }
43 -(NSString *)name{
44     return [[_namename retain]autorelease];
45 }
46 -(void)setGender:(NSString *)gender{
47     if (_gendergender != gender) {
48         [_gendergender release];
49         _gendergender = [[gender retain]autorelease];
50     }
51 }
52 -(NSString *)gender{
53     return [[_gendergender retain]autorelease];
54 }
55 -(void)setAddress:(NSString *)address{
56     if (_addressadress != address) {
57         [_addressadress release];
58         _addressadress = [[address retain]autorelease];
59     }
60 }
61 -(NSString *)address{
62     return [[_addressadress retain]autorelease];
63 }
64 //便利构造器
65 + (Person *)initWithName:(NSString *)name
66                   gender:(NSString *)gender
67                      age:(NSInteger)age
68                  address:(NSString *)address{
69     Person * per = [[Person alloc]initWithName:name gender:gender age:age address:address];
70     return per;
71 }
72 -(NSString *)description{
73     return [NSString stringWithFormat:@"name = %@ ",self.name];//可以这样写
74 //    return [NSString stringWithFormat:@"name = %@  gender = %@ age= %ld adress= %@",_namename,_gendergender,_ageagea,_addressadress];
75 }
76 @end
View Code  Person.m文件
 1 //
 2 //  Student.h
 3 //  Even
 4
 8 
 9 #import "Person.h"
10 
11 @interface Student : Person
12 
13 @property(nonatomic,copy,readonly)NSString * school;
14 @property (nonatomic,retain,readwrite)NSString * stunum;
15 //初始化
16 -(id)initWithName:(NSString *)name
17            gender:(NSString *)gender
18               age:(NSInteger)age
19           address:(NSString *)address
20               stunum:(NSString *)stunum
21            school:(NSString *)school;
22 //便利构造器
23 +(Student *)studentWithName:(NSString *)name
24            gender:(NSString *)gender
25               age:(NSInteger)age
26           address:(NSString *)address
27               stunum:(NSString *)stunum
28            school:(NSString *)school;
29 -(NSString *)description;
30 @end
View Code  Student.h文件
 1 //
 2 //  Student.m
 3 //  Even
 4 
 8 
 9 #import "Student.h"
10 
11 @implementation Student
12 @synthesize school = _school;
13 @synthesize stunum = _stunum;
14 //自己设置setter getter 方法
15 -(void)setSchool:(NSString *)school{
16     if (_school != school) {
17         [_school release];
18         _school = [[school retain]autorelease];
19     }
20 }
21 -(NSString *)school{
22     return [[_school retain]autorelease];
23 }
24 //初始化
25 -(id)initWithName:(NSString *)name
26            gender:(NSString *)gender
27               age:(NSInteger)age
28           address:(NSString *)address
29               stunum:(NSString *)stunum
30            school:(NSString *)school{
31     self = [self init];
32     if (self) {
33         self.name = name;
34         NSLog(@"%@",name);
35         self.gender = gender;
36         self.age = age;
37         self.address = address;
38         self.stunum = stunum;
39         self.school = school;
40     }
41     return self;
42 }
43 //便利构造器
44 +(Student *)studentWithName:(NSString *)name
45                      gender:(NSString *)gender
46                         age:(NSInteger)age
47                     address:(NSString *)address
48                      stunum:(NSString *)stunum
49                      school:(NSString *)school{
50     Student *  stu = [[Student alloc]initWithName:name  gender:gender age:age address:address stunum:stunum school:school];
51     return stu;
52 }
53 -(NSString *)description{
54 //    NSString * name = self.name;
55     return [NSString stringWithFormat:@"%@",self.name];
56 //    return [NSString stringWithString:@"name = %@  gender = %@   age= %ld address = %@   stunumber = %@  school = %@",name,stu.gender,stu.age,stu.address,stu.stunum,stu.school];
57 }
58 @end
View Code Student.m文件

  

首先概念:setter和getter方法。

在OC中,为单一的实例变量赋值的方法称为setter方法,读取实例变量的值得方法称为getter方法。

如:NSInteger _age;

OC中setter方法是这样规定的:

声明部分:

-(void)setter:(NSInteger)age; //setter方法 (注意: set +实例变量名( 首字母 大写),忽略下划线)。

-(NSInteger)age;//getter方法(注意:返回值类型与变量类型 致, 法与实例变量名相同,忽略下划线)。

下面是两种方法的实现部分:

-(void)setter:(NSInteger)age

{

    _age = age;

}

-(NSInteger)age

{

   return _age;

}

由上面方法可以看出,一旦一个项目工程中有多个实例变量参与,那将会引入多个settergetter方法的编写,导致代码繁琐,影响开发周期,为此OC2.0开始出现了属性的点语法操作,这样一来大大简化了程序员的开发难度。

下面看看属性的点语法(又称语法糖):

以实例变量_name为例:
属性的声明
@property NSString *name; 相当于在@interface中声明了两个方法:
 setter和getter方法:
- (void)setName:(NSString *)name;
- (NSString *)name;
属性的实现:在.m 文件使用@synthesize实现属性 ;以实例变量_name为例:
属性的实现:
@synthesize name = _name;

Objective <wbr>C学习第三节:属性和点语法

相当于在@implementation实现了
setter和getter方法
- ( void) setName:(NSString*)name
 { 
    _name = name;
}
getter方法:
- (NSString *)name 
{
  return _name;
}
@ synthesize在类的实现部分。
在Xcode4.5以及之后的版本中,@synthesize可以省略,只使  @property声明属性即可。在默认情况下,当没有实现 setter和getter方法时, 通过 @ synthesize可以自动生成标准的setter和getter法。
如果操作的实例变量未定义,系统会自动生成 一个_属性名的实例变量,但是这个实例变量是私有的,其子类不可以使用。
 一旦同时重写了setter和getter,并且没有实现@synthesize,@synthesize就不再 成实例变量。
  • 属性的特性
Objective-C提供属性的目的是为了简化程序员的编码。 为属性提供了一些关键字以控制setter和getter的实现细节。
这些关键字我们称为属性的特性(attribute)。
读写性:

readonly:只读状态,是告诉编译器,属性只成getter方法。

readwrite:读写状态,是告诉编译器属性即生成setter又生成getter方法。

  • 原子性:
  • 原子性控制(nonatomic, atomic)

atomic:原子特性,settergetter方法在多线程访问下是绝对安全的,即settergetter内部做了多线程访问的处理。默认的原子特性。

nonatomic:非原子性。settergetter方法内部都不会做多线程访问处理,仅仅是普通的settergetter方法。

  • 原子性的控制使用:

程序开发的过程中,setter、getter会频繁使用,如果使用atomic需要不断对settergetter加锁解锁以保证多线程的安全性访问,但是这样会占用很多系统资源,降低系统的性能,(多线程的使用之后我会详细讲解)

声明属性时,通常使用nonatomic,某些属性需要多线程的安全时候,才会去定义为atomic。

例如:@property(nonatomic)NSString* name;

  • 语义设置(assign retaincopy)

如果属性是非对象类型(普通类型如int float double array,枚举),属性的语义设置使用assign.

如果属性是对象类型的,属性的语义设置为retain。

如果属性是对象类型并且想得到对象的副本,使用copy(对于retain和copy的区别内存管理会讲解很透彻滴)。

如果语义设置关键字是assign:

@property(nonatomic, assign)NSInteger age;

  • setter方法的内部实现:

-(void)setAge:(NSInteger)age

{

  _age = age;

}

  • getter内部实现:

-(NSInteger)age

{

  return _age;

}

如果语义设置是retain,@property(nonatomic, retain)NSString* name;

setter方法内部实现是这样的:

-(void)setName:(NSString*)name

{

  if(_name != name)

   {

      [_name release];

       _name = [name retain];

   }

}

getter内部方法实现如下:

-(NSString*)name

{

  return [ [_name retain] autorelease ];

}

如果语义设置的关键字是copy。例如:
@property (nonatomic, copy) NSString *gender;
  •  setter的内部实现
 - (void)setGender:(NSString *)gender
 {
   if (_gender != gender)
     {
         [_gender release];
          _gender = [gender copy];

      }

}

  • getter内部实现:

-(NSString*)gender

  return [ [ _gender retain] autorelease];

}

  • 点语法

定义:点语法是OC2.0中定义的语法格式,提供了一种便捷的属性访问方式。

点语法的使用:只要符合系统默认的setter getter书写格式的方法都可以使用点语法。

例如实例变量 _name

  • setter方法   

[person  setName:@"Rephontil"];

使用点语法替换为: person.name = @"Rephontil";

  • getter方法:

NSString* string = [person name];

使用点语法的写法:  NSString* string = person.name;

属性是一对setter getter方法,点语法是属性的另一种调用格式。

原文地址:https://www.cnblogs.com/benpaobadaniu/p/4744021.html