zoukankan      html  css  js  c++  java
  • 协议和代理

    1.协议基本概念

    什么是协议?

    • 其他语言有接口的概念,接口就是一堆方法的声明没有实现.
    • OC中没有接口的概念,OC中的接口就是协议.
    • 协议Protocol是由一系列的方法声明组成的

    书写协议的格式?

    格式:

    @protocol 协议名称 <NSObject>
    // 方法声明列表
    
    @end

    一个类怎么遵循协议?

    类遵守协议格式:

    @interface 类名 : 父类 <协议名称1, 协议名称2,…>

    @end

    注意:

    1. 一个类可以遵守1个或多个协议
    2. 任何类只要遵守了Protocol,就相当于拥有了Protocol的所有方法声明

    协议和继承区别

    1. 继承之后默认就有实现, 而protocol只有声明没有实现
    2. 相同类型的类可以使用继承, 但是不同类型的类只能使用protocol
    3. protocol可以用于存储方法的声明, 可以将多个类中共同的方法抽取出来, 以后让这些类遵守协议即可

    2.协议注意事项

    什么是基协议?

    • 基协议:是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。
    • 注意:建议每个新的协议都要遵守NSObject协议

    协议有哪些注意事项?

    1. 协议只能声明方法, 不能声明属性
    2. 父类遵守了某个协议, 那么子类也会自动遵守这个协议
    3. 在OC中一个类可以遵守1个或多个协议 注意: OC中的类只能有一个父类, 也就是说OC只有单继承
    4. OC中的协议又可以遵守其它协议, 只要一个协议遵守了其它协议, 那么这个协议中就会自动包含其它协议的声明

    协议中控制方法的能否实现的关键字是什么?各有什么作用?

    1. 注意: 如果没有使用任何关键字修饰协议中的方法, 那么该方法默认就是required的
    2. 注意: @required和@optional仅仅使用程序员之间交流, 并不能严格的控制某一个遵守该协议的类必须要实现该方法, 因为即便不是实现也不会报错, 只会报一个警告
    3. @required 如果协议中的方法是@required的, 要求遵守协议的类实现@required所修饰的方法,如果没有实现该方法, 那么会报一个警告
    4. @optional 如果协议中的方法是@optional的, 遵守协议的类可选择实现@optional所修饰的方法,如果没有实现该方法, 那么不会报警告

    3.协议应用场景1-类型限定

    问题1:什么是类型限定?

    答:类型限定就是限定一个类必须遵守某个协议

    问题2:类型限定的格式?

    答: 数据类型<协议名称> 变量名

    @property (nonatomic, strong) Wife<WifeCondition> *wife;

     

    类型限定注意点

    1. 类型限定是写在数据类型的右边的
    2. 虽然在接受某一个对象的时候, 对这个对象进行了类型限定(限定它必须实现某个协议), 但是并不意味着这个对象就真正的实现了该方法. 所以每次在调用对象的协议方法时应该进行一次验证
    if ([self.wife respondsToSelector:@selector(cooking)]) {
    
    [self.wife cooking];
    }

    代理模式的应用场景?

    1.当A对象想监听B对象的一些变化时, 可以使用代理设计模式 保姆想监听婴儿的变化, 那么保姆就可以成为婴儿的代理, 当婴儿发生变化之后保姆就可以监听到

    2.当B对象发生一些事情, 想通知A对象的时候, 可以使用代理设计模式 婴儿想通知保姆, 那么就可以 让保姆成为婴儿的代理, 只要保姆成为婴儿的代理, 以后婴儿发生变化就可以通知保姆

    3.当对象A无法处理某些行为的时候,想让对象B帮忙处理(让对象B成为对象A的代理对象) 婴儿无法自己吃东西, 也无法自己入睡, 所以可以让保姆帮忙处理. 只要让保姆成为婴儿的代理就可以帮婴儿喂它吃东西和哄他睡觉

    用什么类型来接收遵守协议的代理对象?

    使用id类型接收代理对象

    // 如果使用id类型来接收保姆, 如果将来换保姆了, 婴儿类不用修改代码

    @property (nonatomic, strong) id<BabyProtocol> nanny;

    问题3:实现代理的有哪几步?(保姆照顾婴儿 吃饭 睡觉)

    答:

    婴儿类中

    1.声明婴儿是一个类(将当前对象传出去) @class Baby;

    2.定义代理协议,协议中声明代理要帮婴儿做的事 (只声明方法,将婴儿传给代理,让代理实现协议中方法,注意协议格式)

    @protocol BabyDelegate <NSObject>
    
    //喂婴儿吃饭
    - (void)eat:(Baby *)baby;
    //哄婴儿睡觉
    - (void)sleep:(Baby *)baby;
    
    @end

    3.将代理作为属性,类型限定代理遵守协议

    @property (nonatomic, weak) id <BabyDelegate> delegate;

     

    4.声明方法,方法里调用代理,调用代理实现的协议方法,让代理帮婴儿吃饭,睡觉

    //婴儿饿了要吃饭
    - (void)hurgry;
    
    //婴儿醒了要睡觉
    - (void)wake;

    5.实现调用代理者的方法

    @implementation Baby
    
    - (void)hurgry{
    
    //    6.判断代理是否实现了协议中的方法
        if ([self.delegate respondsToSelector:@selector(eat:)]) {
            //7.如果代理实现了协议中的方法,就调用
            [self.delegate eat:self];
        }
    }
    
    - (void)wake{
        if ([self.delegate respondsToSelector:@selector(sleep:)]) {
            [self.delegate sleep:self];
        }
    }
    @end

    代理类中

    8.导入代理

    @protocol BabyDelegate;

     

    9.遵守代理

    @interface Nurse : NSObject <BabyDelegate>
    
    @end

    10.实现协议中的方法,(喂婴儿,让婴儿吃饭,拿到婴儿才能给婴儿做事)

    @implementation Nurse
    
    - (void)eat:(Baby *)baby{
        baby.hurgryValue += 10;
        NSLog(@"喂婴儿吃饭!饥饿值:%lu", baby.hurgryValue);
    
    }
    
    - (void)sleep:(Baby *)baby{
        baby.sleepValue += 5;
    
    NSLog(@"摇婴儿睡觉!疲劳值:%lu", baby.sleepValue);
    }
    @end

    main函数中

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    
    //11.创建所需对象
            Baby *b = [[Baby alloc]init];
            Nurse *n = [[Nurse alloc]init];
    
    //12.将代理对象作为接受代理者的代理
            //(让保姆作为婴儿的代理)
            b.delegate = n;
    
    //设定婴儿初始饥饿值,疲劳值
            b.hurgryValue = -5;
            b.sleepValue = -5;
    
    //13.接受代理者调用代理者的方法
            //(婴儿饿了,醒了,需要吃饭和哄一哄)
            [b hurgry];
            [b wake];
        }
        return 0;
    }

    5.代理设计模式练习及规范

    协议的编写规范

    1. 一般情况下, 当前协议属于谁, 我们就将协议定义到谁的头文件中
    2. 协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegate
    3. 协议中的方法名称一般以协议的名称protocol之前的作为开头
    4. 一般情况下协议中的方法会将触发该协议的对象传递出去
    5. 一般情况下一个类中的代理属于的名称叫做 delegate
    6. 当某一个类要成为另外一个类的代理的时候, 一般情况下在.h中用@protocol 协议名称;告诉当前类 这是一个协议. 在.m中用#import真正的导入一个协议的声明
  • 相关阅读:
    进程间通讯,线程间通讯
    进程与线程
    学习自测6.0
    学习自测5.0
    学习自测4.0
    学习自测3.0
    学习自测2.0
    学习自测1.0
    PS中怎么复制某个图层的效果?
    初学前端犯下的错误(用于反省)
  • 原文地址:https://www.cnblogs.com/dreamWanweidong/p/4997973.html
Copyright © 2011-2022 走看看