[OC]-<协议 “(protocol)“ 与委托(delegate)>

协议

协议是OC的知识点之一,其作用类似于接口,用于定义多个类应该组瘦的规范

规范、协议And接口

    • OC语言中的协议的作用就相当于其他语言的接口作用
      在这里插入图片描述
    • 同一个类的内部状态数据,各种方法的实现细节完全相同,类是一种具体的实现体,而协议则定义了一种规范、

协议之规定着疲累中必须提供某些方法,提供这些方法的类就可以满足实际需要
协议不提供任何实现

这样理解协议

  • 协议定义的是多个类共同的公共行为规范,这些行为与外部交流的通道,这就意味着协议里通常定义的是一组共用方法,但协议不为这些方法进行实现,实现交给完成

使用类别实现非正式协议

当某个类实现NSObject的该 类别是,就需要实现该类别下的所有方法,这种基于NSObject定义的类别可以认为是 非正式协议

非正式协议实例

#import <Foundation/Foundation.h>

//协议
@interface NSObject  (eatable)
-(void) taset;

@end

//子类
@interface fkapple : NSObject

@end

@implementation fkapple
// 协议里方法的实现
-(void) taset {
    NSLog(@"这个苹果好吃滴很");
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        fkapple *apple = [[fkapple alloc] init];
        [apple taset];
    }
    return 0;
}



//打印


2022-05-21 16:19:19.766639+0800 OC协议与委托[5348:759981] 这个苹果好吃滴很
Program ended with exit code: 0
关于这个代码
  • 从上面的代码可以看出 fkapple 类实现了taste方法,这样子fkapple就相当于遵守了eatable协议,接下来把fkapple类当eatabe对象调用
  • 如果上面的fkapple类不实现taste方法,并且非正式协议本身彬哥密友实现该方法,那么该程序运行时就报错
  • 在这里插入图片描述
    这就是我注释了taste的实现并且在协议里也没有实现,希望读者注意

正式协议的定义

  • 和定义类有区别的是正式协关键字议不在用@interface 和@implementation关键字,
  • 使用@protocol关键字

正式协议@protocol语法

   @protocol 协议名 <父协议1,父协议2> {
    0到多个方法的定义
   }
语法说明

对上面语法格式的详细说明如下。

  • 协议名应与类名采用相同的命名规则。即如果仅从语法角度来看,协议名只要是合法的标识符即可:如果要遵守 Objective-C可读性规范,则协议名应由多个有意义的单词连接而成,每个单词首字母大写,单词与单词之间无须任何分隔符。
  • 一个协议可以有多个直接父协议,但协议只能继承协议,不能继承类。
  • 协议中定义的方法只有方法签名,没有方法实现;协议中包含的方法既可是类方法,也可是实例方法
    前面己经说过了,协议定义的是多个类共同的公共行为规范,因此,协议里所有的方法都具有 公开访问权限

正式协议实例

//2.正式协议的定义
#import <Foundation/Foundation.h>

//1.定义一个fkOutput协议
@protocol fkOutput

//该协议的2个方法
//只要某个类满足下面的方法
-(void) output;
-(void) addData: (NSString*) msg;

@end

//2.定义一个fkproductable协议
@protocol fkproductable

// 该协议的方法返回产品的生产时间
//----------无论是哪种产品都应该提供一个getProduceTime 方法开获取该产品的生产时间
- (NSDate*) getProduceTime;

@end


//3.定义一个打印机协议 还协议同时继承上面的两个协议
@protocol fkPrintable <fkOutput, fkproductable>
//这里可以看出协议完全支持多继承,记一个协议可以多很多个父协议
//-------类似的,子协议继承某个父协议,将会获得父协议的所有方法

//打印机方法
-(NSString*) printColor;
@end


正式协议特点
  • 这里可以看出协议完全支持多继承,记一个协议可以多很多个父协议
    类似的,子协议继承某个父协议,将会获得父协议的所有方法

实现协议

  • 在类的接口部分可以指定该类继承的父类及遵守的协议
实现协议的语法
 @interface 类名 :父类<协议1,协议2.。。。。>
  • 这里同样可以看出 一个类可以同时遵守多个协议
实现类
  • 为fkprintable 协议 提供一个实现类:fkPrinter
/实现协议的类 - fkPrinter
//1.接口部分
@interface fkPrinter : NSObject <fkPrintable>

@end
//
//2。实现部分
@implementation fkPrinter {
    NSString* printData[30];//数组记录所有需要缓存的打印数据
    
    //记录当前需要打印的作业数
    int dataNum;
}
-(void) output {
    //需要打印的作业还有-循环继续
    while (dataNum > 0) {
        NSLog(@"打印机使用%@打印 :%@", self.printColor, printData[0]);
        //剩余作业减一
        dataNum --;
        //作业整体向前移动一位
        for (int i = 0; i < dataNum; i++) {
            printData[i] = printData[i + 1];
        }
    }
}

-(void) addData :(NSString*) msg {
    if (dataNum >= 30) {
        NSLog(@"输出队列嘛满了,添加失败");
    } else {
        printData[dataNum ++] = msg;
    }
}

-(NSDate*) getProduceTime {
    return [[NSDate alloc] init];
}
-(NSString*) printColor {
    return @"无敌炫酷缤纷大红色";
}
@end

//fkprinter类的实现 实现了fkprintable协议,并且也实现了fkoutput fkproductable两个父协议的所有方法,
//假如实现类未实现协议中的printfColor方法 编译器会如下警告

int main() {
    @autoreleasepool {
        // 创建一个对象
        fkPrinter* p1 = [[fkPrinter alloc] init];
        // 调用fkPrinter 对象的方法
        [p1 addData:@"疯狂lyt讲义"];
        [p1 addData:@"疯狂iOS学习!"];
        [p1 output];
        [p1 addData:@"疯狂3g都在学习"];
        [p1 addData:@"疯狂iOS组今天没人!"];
        [p1 output];
        // p1程序是fkprinter对象,该对象包含上面3个i协议的方法,因此可以调用3个协议中的方法
    }
}


2022-05-21 17:34:38.703607+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂lyt讲义
2022-05-21 17:34:38.703805+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂iOS学习!
2022-05-21 17:34:38.703825+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂3g都在学习
2022-05-21 17:34:38.703838+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂iOS组今天没人!
Program ended with exit code: 0
  • p1程序是fkprinter对象,该对象包含上面3个i协议的方法,因此可以调用3个协议中的方法

使用协议来定义变量

  • 若果程序需要使用协议来定义变量,有如下两种语法

    NSObject<协议1,协议2....>* 变量
    id<协议1,协议2....> 变量;
    

注意
使用上面语法格式定义的变量,它们编译时类型仅仅是所遵守的协议剋下,因此只能调用该协议中定义的方法

协议定义变量实例
int main() {
    @autoreleasepool {
        //创建一个fkprinter对象,当成fkproductable使用
        //1.NSObject<协议1,协议2....>* 变量语法
        NSObject<fkproductable> *p = [[fkPrinter alloc] init];
        // 调用fkproductable 协议中定义的方法
        NSLog(@"%@", p.getProduceTime);
    
        
        //2.  id<协议1,协议2....> 变量;
        //创建一个fkprinter对象,当成fkoutput使用
        id<fkOutput> out = [[fkPrinter alloc] init];
        [out addData:@"勒布朗"];
        [out addData:@"扬尼斯"];
        [out addData:@"lyt"];
        [out addData:@"阿道"];
        [out output];
    }
}


在这里插入图片描述

关于正式协议与非正式协议

对比正式协议与非正式协议,不难发现存在如下差异。

  • >非正式协议通过为 NSObject 创建类别来实现:而正式协议则直接使用@protocol 创建。
  • >遵守非正式协议通过继承带特定类别的 NSObject 来实现:而遵守正式协议则有专门的Objective-C 语法。
  • >遵守非正式协议不要求实现协议中定义的所有方法:而遊守正式协议则必须实现协议中定义的所有方法。

为了弥补遵守正式协议必须实现协议的所有方法造成的灵活性不足,Objective-C 2.0 新增了@optional、 @required 两个关键字,其作用如下。

  • @optional:位于该关键字之后、@optional 或@end 之前声明的方法是可选的•实现类既可选择实现这些方法,也可不实现这些方法。
    @required: 位于该关键字之后、@required 或@end 之前声明的方法是必需的实现
    类必须实现这些方法。如果没有实现这些方法,编译器就会提示警告。@required 是默认行为

      @protocol fkoutput
      @optional
       (void) output; //由于@optiona关键字所以可选择的实现output
       @required
       (void) addData :(NSString*) msg; // addData 必须实现否则系统警告
       @end
    

有了@optional @required 关键字 正式协议可以完全替代非正式协议

委托和协议

协议体现的是一种规范,定义协议的类可以吧协议定义的方法委托给实现协议的类,这样可以让类的定义具有更好的通用性

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值