OC学习_6_OC特有_属性、协议和代理

======文档更新状态=====
2015-12-18:发布

==================

day06-2015-12-17
一、属性

1.简单的封装技术,可以自动生成相应代码
2.语法:声明(接口)部分使用@property;
实现部分使用@synthesize(OC1.0是必须要写的,OC2.0基本都省略不写)
3.当使用对象指针指向对象实例时,可以使用.运算符访问getter和setter;而id类型不可以,只能通过方法调用
4.如果要对数据进行有效性处理,则需要在实现部分重写setter
5.如果想设为只读,则需在@property后面增加一对小括号,在小括号里增加修饰符:readonly (默认:readwrite)
关于修饰符:
A.readonly和readwrite
B.atomic和nonatomic
一般单线程程序使用nonatomic,多线程使用atomic
C.setter和getter:重新定义属性对应得get方法和set方法名;一般BOOL类型的属性需要重新定义getter;注意setter方法名必须以:结尾
D.assign,retain,copy
E.strong,weak,unsafe_unretained
一些通俗解释
属性
1.一种简化的封装技术
2.语法:在@interface中使用@property指令声明即可,老版本(iOS6之前)还需要在@implementation中使用@synthesize生成,默认情况下使用@synthesize生成的成员变量与属性同名,而不使用@synthesize时,成员变量名以下划线开头
3.使用:既可以使用简化的.运算符,也可以使用方法访问
4.默认情况下getter和setter按照属性名生成,getter与属性名相同,setter在属性名前加set并改属性名首字母大写;除了BOOL类型需要指定getter外,一般不建议修改默认的getter和setter
5.如果指定了属性的getter和setter,则对使用方法访问属性造成影响,但对.运算符没有任何影响
6.readonly(只读,不产生setter,一般由init家族方法进行赋值)和readwrite(读写,默认)
7.atomic和nonatomic:多线程程序中需要在数据安全性和性能之间平衡,单线程中只要考虑性能即可
8.内存管理相关(ARC:Automatic Reference Counting,和MRC对应)
A.assign:基本类型固定使用,对象指针也可以,但对RC无影响
B.retain:对象指针使用,对RC有影响
C.copy:对象指针使用,遵循NSCopying协议的对象才可以使用
D.weak(仅用于ARC)
E.strong(仅用于ARC)
F.unsafe_unretained(仅用于ARC)
// 注意下面.h文件中属性的写法

//  YYPerson.h
#import <Foundation/Foundation.h>

@interface YYPerson : NSObject
@property (nonatomic,assign) int age;//属性
@property (getter=isMarried,assign) BOOL married;
@property (readonly) NSString* name;
-(instancetype)initWithName:(NSString*)name age:(int)age;
@end
//  YYPerson.m
/
//

#import "YYPerson.h"

@implementation YYPerson
//@synthesize age=_age;//age
-(NSString *)description{
    return [NSString stringWithFormat:@"person %@'s age is %d",_name,_age];
}
-(void)setAge:(int)age{
    if (age<0 || age>150) {
        _age=10;
    }
    else{
        _age=age;
    }
}


-(instancetype)initWithName:(NSString *)name age:(int)age{
    if (self=[super  init]) {
        self->_name=[name copy];
        self.age=age;
    }
    return self;
}

@end
//  main.m

#import "YYPerson.h"

int main_property(int argc, const char * argv[]) {
    YYPerson* p1=[YYPerson new];
    p1.age=-100;
    NSLog(@"age:%d",p1.age);//10
    p1.married=YES;
    NSLog(@"married:%d",p1.married);
    NSLog(@"married:%d",[p1 isMarried]);
    NSLog(@"---------------");
    YYPerson* p2=[[YYPerson alloc]initWithName:@"mike" age:200];
    NSLog(@"p2:%@",p2);

    return 0;
}

二、协议protocol
1.仅有方法声明,没有方法实现,也没有成员变量和属性
2.可以实现“多继承”结构
3.语法:
A.定义协议
@protocol 协议名 <父协议>
//方法声明
@end
B.遵循协议
@interface 子类名:父类<协议名>
//子类自己新增的成员变量、属性、方法等
@end
C.创建对象
使用对象指针加协议名(可以访问指针类型中的方法以及协议中的方法)或id加协议名(只能访问协议中的方法)
一些通俗解释
协议@protocol
1.协议只是方法规范,无实现,一个类可以遵循多个协议,但要给出每个协议中声明的方法的实现
2.语法:
@protocol 协议名 [<父协议,…>]
//方法声明
@end
3.使用
A.子类遵循:
@interface 子类名:父类名<父协议名>
//自己的成员变量、属性、方法等声明
@end
B.对象创建
a).使用本类指针指向本类对象,所有父类、自身类以及协议中的方法、属性都可以
b).使用父类指针指向子类对象,只能访问所有父类的方法、属性
c).使用父类指针加协议名指向子类对象,所有父类以及协议中的方法、属性都可以
d).使用id类型,当前环境下所有能够访问到的方法,但是不保证能够执行成功
e).使用id类型加协议名,只能访问协议中的方法
C.多个协议:基本概念与单协议相同,需要访问哪些协议中的方法,就在父类指针或id后面加上相应的协议名,可以加多个
4.协议继承,可以多继承,但最好还是要符合is a关系
5.关于必须@required和可选@optional:必须和可选的区别仅仅是在子类中如果没有实现是否给出警告信息(必须的有警告,可选的没有),如果未实现时去访问能够通过编译,但运行时还是会出错
// protocol的关于对象创建的例子

//  YYFighting.h

#import <Foundation/Foundation.h>

@protocol YYFighting <NSObject>
-(void)fight;
@end
//  YYPerson.h

#import <Foundation/Foundation.h>

@interface YYPerson : NSObject
@property (nonatomic,assign) int age;//属性
@property (getter=isMarried,assign) BOOL married;
@property (readonly) NSString* name;
-(instancetype)initWithName:(NSString*)name age:(int)age;
@end
//  YYPerson.m

#import "YYPerson.h"

@implementation YYPerson
//@synthesize age=_age;//age
-(NSString *)description{
    return [NSString stringWithFormat:@"person %@'s age is %d",_name,_age];
}
-(void)setAge:(int)age{
    if (age<0 || age>150) {
        _age=10;
    }
    else{
        _age=age;
    }
}


-(instancetype)initWithName:(NSString *)name age:(int)age{
    if (self=[super  init]) {
        self->_name=[name copy];
        self.age=age;
    }
    return self;
}

@end
//  YYSoldier.h

#import "YYPerson.h"
#import "YYFighting.h"

@interface YYSoldier : YYPerson<YYFighting>
@property (nonatomic,assign)int level;
@end
#import "YYSoldier.h"

@implementation YYSoldier
-(void)fight{
    NSLog(@"%@ is fighting.",self.name);
}

@end
#import "YYSoldier.h"
int main_protocol1(){
    //使用本类指针指向本类对象
    YYSoldier* s1=[[YYSoldier alloc]initWithName:@"mike" age:33];
    [s1 fight];//协议的
    [s1 setAge:10];//父类的
    [s1 setLevel:100];//自己的
    //使用父类指针指向子类对象
    YYPerson* p1=[[YYSoldier alloc]initWithName:@"jerry" age:22];
    [p1 setAge:20];//父类的
//    [p1 fight];
//    [p1 setLevel:100];
    //使用父类指针加协议名指向子类对象
    YYPerson<YYFighting>* p2=[[YYSoldier alloc]initWithName:@"andy" age:26];
    [p2 setAge:20];//父类的
[p2 fight];//协议的

//    [p2 setLevel:100];
    //使用id类型
    id t1=[[YYSoldier alloc]initWithName:@"tom" age:36];
    [t1 setAge:10];
    [t1 setLevel:2000];
    [t1 fight];
//    [t1 stringByAppendingString:@"fff"];//能通过编译,运行出错
    id<YYFighting> t2=[[YYSoldier alloc]initWithName:@"marry" age:31];
    [t2 fight];
    [t2 description];
    NSObject<YYFighting>* t3;
    [t3 description];
    return 0;
}

关于protocol的重点强调
对象创建
a).使用本类指针指向本类对象,所有父类、自身类以及协议中的方法、属性都可以
b).使用父类指针指向子类对象,只能访问所有父类的方法、属性
c).使用父类指针加协议名指向子类对象,所有父类以及协议中的方法、属性都可以
d).使用id类型,当前环境下所有能够访问到的方法,但是不保证能够执行成功
e).使用id类型加协议名,只能访问协议中的方法
C.多个协议:基本概念与单协议相同,需要访问哪些协议中的方法,就在父类指针或id后面加上相应的协议名,可以加多个

三、代理协议
1.目标:自己类不去完成、实现具体操作,而是交给别的类的对象(即:代理)去做
2.思路:
A.定义一个代理协议,规定好代理应该具有的功能(即:方法声明)
B.定义一个主类,包含一个代理属性以及若干功能,其中某些功能在实现时,直接交给代理属性去做,而不自己实现
C.创建若干遵循代理协议的子类,分别实现代理协议中规定的方法
D.在创建主类对象后,调用应该由代理去做的方法前,给代理属性赋上一个代理子类的对象
一些通俗解释
设计模式:代理delegate
1.自己不做,交给代理做(如果有代理,交给代理做;如果没有代理就自己做)
2.实现步骤
A。定义一个协议,规定一些代理所必须遵守的规范(方法)
B。再定义若干代理子类,遵循该协议,并给出方法的实现
C。在主类中定义一个协议类型的成员变量或属性
D。在主类中声明一些方法,在实现时调用遵循了代理协议的子类对象的方法,而不是自己去做具体事情
3.注意事项:任何由nil访问的方法都不会执行,如:NSObject* obj=nil;
[obj buy];//不执行
如果方法有返回值类型,则一律以各种0表示
// 代理模式的一个例子

//  YYManager.h
//  主类:需要用到代理的类
// 
//

#import "YYAssistant.h"

@interface YYManager : NSObject
@property (nonatomic,weak) id<YYAssistant> delegate;
-(void)write;
-(void)buy;
-(void)say;
-(int)eat;
@end
//  YYManager.m
#import "YYManager.h"

@implementation YYManager
-(void)buy{
// 如果有代理就让代理做,如果没有代理就自己做
    if (_delegate!=nil) {
        //如果_delegate不为nil时,交给代理执行
        [_delegate buyTicket:@"NJ" to:@"BJ"];
    }
    else {
        NSLog(@"经理自己买机票。");
    }

}

-(void)write{
    if (_delegate!=nil){
        [_delegate writeDoc];
    }
    else{
        NSLog(@"经理自己写文章。");
    }
}

-(void)say{
    NSLog(@"经理说话");
}
-(int)eat{
    return 100;
}
@end
// YYAssistant.h
//  代理协议:定义一个助理所需要完成的事情
//  1.写文章
//  2.买机票
//
//

#import <Foundation/Foundation.h>

@protocol YYAssistant <NSObject>
-(void)writeDoc;
-(void)buyTicket:(NSString*)from to:(NSString*)to;

@end
//  YYGoodAssistant.h
#import "YYAssistant.h"

@interface YYGoodAssistant : NSObject<YYAssistant>

@end
//  YYGoodAssistant.m
#import "YYGoodAssistant.h"

@implementation YYGoodAssistant
-(void)writeDoc{
    NSLog(@"写了一篇流芳百世的文章!");
}

-(void)buyTicket:(NSString *)from to:(NSString *)to{
    NSLog(@"买了一张从%@到%@的机票。",from,to);
}
@end
//  YYFoolAssistant.h

#import "YYAssistant.h"

@interface YYFoolAssistant : NSObject<YYAssistant>

@end
//  YYFoolAssistant.m

#import "YYFoolAssistant.h"

@implementation YYFoolAssistant
-(void)writeDoc{
    NSLog(@"写了一篇遗臭万年的文章!");
}

-(void)buyTicket:(NSString *)from to:(NSString *)to{
    NSLog(@"买了一张从%@到%@的机票。",to,from);
}
@end
//  test_delegate.m
/

#import "YYManager.h"
#import "YYGoodAssistant.h"
#import "YYFoolAssistant.h"
int main(){
    YYManager* ma=[YYManager new];
//    YYGoodAssistant* ga=[YYGoodAssistant new];
//    YYFoolAssistant* ga=[YYFoolAssistant new];
//    ma.delegate=ga;
    [ma buy];
    [ma write];

    return 0;
}
关于代理的一些总结:
1>实现步骤
A。定义一个协议,规定一些代理所必须遵守的规范(方法)
B。再定义若干代理子类,遵循该协议,并给出方法的实现
C。在主类中定义一个协议类型的成员变量或属性
D。在主类中声明一些方法,在实现时调用遵循了代理协议的子类对象的方法,而不是自己去做具体事情
2>@property (nonatomic,weak) id<YYAssistant> delegate;
这里的id<YYAssitant>表示当前对象不知道他的代理的类型只是知道
它的代理必须遵循YYAssistant协议
3>注意体会代理设计模式思想
5>  IOS中是这样使用代理的:
如果有代理就让代理做,否则就自己做
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值