zoukankan      html  css  js  c++  java
  • 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方法,点语法是属性的另一种调用格式。

  • 相关阅读:
    MySQL使用alter修改表的结构
    MySQL基本库表管理
    MySQL的rpm安装教程
    MySQL基础理论
    Linux shell awk数组使用
    Linux shell awk逻辑控制语句
    Linux shell awk模式使用
    MySQL 查看执行计划
    MySQL 自定义函数
    MySQL 内置函数
  • 原文地址:https://www.cnblogs.com/benpaobadaniu/p/4744021.html
Copyright © 2011-2022 走看看