• Object C学习笔记15-协议(protocol)


      在.NET中有接口的概念,接口主要用于定义规范,定义一个接口关键字使用interface。而在Object C 中@interface是用于定义一个类的,这个和.NET中有点差别。在Object C中有一个协议(protocol) 的概念,这个和.NET中的interface类似。

      协议(Protocol) 在列出的方法在本类中并没有相应实现,而是别的类来实现这些方法,而定义协议必须使用protocol关键字。

      一. 如何定义protocol的定义

        如何使用XCode新建一个协议.h 文件

     

     

     

     

     

     

     

     

    定义协议代码如下:

    #import <Foundation/Foundation.h>
    
    @protocol ProtocolCom <NSObject>
    
    @required
    -(void) eat;
    
    @optional
    -(void) write;
    
    @end
    定义协议代码

        从以上代码可以看到,我们可以了解到定义一个协议基本如下结构:

        @protocol protocolName<NSObject>

        @required

        //方法声明

        @optional

        //方法声明

        .......

        @end

    从刚才的代码中,定义了一个名为ProtocolCom的协议,其中有两个方法 eat ,write;  上面也提到过了,protocol相当于.net中的interface 接口,接口就是用于定义规则的,但是Object C中的协议和.NET中的interface还是有点区别的,这里就涉及到@required,@optional 。 这两个标注在方法上面是有特殊含义的,这个后面详细说明。

    #import <Foundation/Foundation.h>
    
    @protocol ProtocolCom 
    
    @required
    -(void) eat;
    
    @optional
    -(void) write;
    
    @end
    修改协议代码

        从上面修改的代码对比来看,在协议定义后面缺少了<NSObject> ,这段代码仍然能够正常运行,其实<NSObject>也本身可以理解为ProtocolCom要遵循NSObject 协议,这个和.NET中一个类如果没有显示指定继承哪个类,那么默认就是继承的Object类的道理是一样的,所以这里可以省略。

        这里我在定义一个协议MyProtocol,这个协议必须遵循协议ProtocolCom协议。刚才上面已经了解到了协议后面跟<NSObject>,道理一样如果MyProtocol要遵循协议ProtocolCom就是用此种方式来实现,具体代码如下:

    #import <Foundation/Foundation.h>
    #import "ProtocolCom.h"
    
    @protocol MyProtocol <ProtocolCom>
    
    @required
    -(void) setname;
    
    @optional
    -(void) setage;
    
    @end
    协议的"继承"

        在Object C 协议中并不习惯说继承,而是是用遵从或者遵循,比如A协议遵循B协议。这里专业上得术语可能不太准确,姑且这么说,先理解意思。

        然后我们是用一个新的类来实现协议MyProtocol中的所有方法。

    #import <Foundation/Foundation.h>
    #import "MyProtocol.h"
    
    @interface Student : NSObject<MyProtocol>
    
    @end
    
    
    
    -------------------------------------------
    #import "Student.h"
    
    @implementation Student
    
    -(void) write{
        NSLog(@"write");
    }
    
    -(void) eat{
        NSLog(@"eat");
    }
    
    -(void) setage{
        NSLog(@"Student---setage");
    }
    
    -(void) setname{
        NSLog(@"Student----setname");
    }
    
    @end
    实现协议代码

        从以上代码可以看出类Student实现了协议MyProtocol,因为协议MyProtocol遵循协议ProtocolCom,所以协议MyProtocol有四个方法。所以在Student类中可以实现四个方法。

      二. 协议相关约束

        @required 用于表示协议中该方法必须在类中实现,默认[如果不加则默认为@required]

        @optional 用于表示协议中该方法在类中可以选择实现

        看到这里貌似比.NET中的要高级点,.NET中interface定义的所有方法在子类中都必须实现。如果用@required标识的方法在子类中没有实现那么编译编译会报错,提示该方法必须实现。而@optional则不会。下面这段代码就会存在问题:

    #import "Student.h"
    @implementation Student
    -(void) write{
        NSLog(@"write");
    }
    -(void) eat{
        NSLog(@"eat");
    }
    -(void) setage{
        NSLog(@"Student---setage");
    }
    @end
    未能实现所有@required标识的方法

        

       三. 同时遵循多个协议

        在.NET中一个类也可以实现多个接口,在Object C中同样如此,一个类可以实现遵循多个接口,基本语法如下:

        @interface className:parentName<ProtocolName1,ProtocolName2,...>

        ......

        @end

        虽然上面简单了点,但是还是能够看明白表达的意思,下面看一段代码说明:

        这里从新定义一个新的协议NewProtocol,里面有一个必须实现的方法getname

    #import <Foundation/Foundation.h>
    @protocol NewProtocol <NSObject>
    @required
    -(NSString*) getname;
    @end
    NewProtocol协议定义

        然后从新定义一个新的类Children,这个类必须遵循协议NewProtocol和协议MyProtocol ,具体代码如下:

    #import <Foundation/Foundation.h>
    #import "MyProtocol.h"
    #import "NewProtocol.h"
    
    @interface Children : NSObject<MyProtocol,NewProtocol>
    
    
    @end
    Children.h 遵循两个协议

        在Children.m代码中要实现两个协议中必须实现的方法

    #import "Children.h"
    
    @implementation Children
    
    
    -(void) eat{
        NSLog(@"eat");
    }
    
    -(void) setname{
        NSLog(@"Student--setname");
    }
    
    -(NSString*) getname{
        return  @"qingyuan";
    }
    @end
    Children.m实现两个协议代码

        下面使用测试代码,看看一个类遵循两个协议的效果:

    Children *child=[[Children alloc] init];
            NSString *name=[child getname];
            NSLog(@"name=%@",name);
            [child eat];
            [child setname];
    测试代码

        在上面的代码中可以正常运行,但是要注意如果可选择实现的方法没有去实现,而在这里去调用的话会报错。

      四. 正式协议和非正式协议

        说道正式协议和非正式协议,其实只要理解两个关键字@interface 和 @protocol 。先看看下面一个列子

    #import <Foundation/Foundation.h>
    #import "MyProtocol.h"
    #import "NewProtocol.h"
    
    @interface Children : NSObject<MyProtocol,NewProtocol>
    
    -(void) love;
    
    @end
    在@interface 定义一个新方法

        在Children.h中定义了一个新的方法love,之前我们也一直这样写的,没有任何问题。再看下面一段代码

    #import "Children.h"
    
    @implementation Children
    
    
    -(void) eat{
        NSLog(@"eat");
    }
    
    -(void) setname{
        NSLog(@"Student--setname");
    }
    
    -(NSString*) getname{
        return  @"qingyuan";
    }
    @end
    Children.m实现的代码

        使用编译器编辑,代码并没有报错。在Children.m中没有love方法的实现。 这个和我们之前所见到的代码似乎有点不一样啊,有点不理解,理论上Children.m中应该实现love方法的。

        上面看到的这种情况,就好比Protocol中的@optional方法,是可以选择实现的,其实我们就称作@interface Children : NSObject 就是一个非正式协议。

    刚才也注意到了,那是不是Protocol中的@optional标识的方法也就是非正式协议呢。在这里网络上有些争议,个人也没有完全明白,但是个人理解这个还是不一样的。@protocol是一种既定的规则,如果要做就必须遵循这种规则,而@interface有点象描述,用于描述类是干什么的. 而两者因为都可选择实现其他的方法,所以感觉有点类似。

      五. 协议总结

        Object C中有点特殊的时协议不引用任何类,任何类都可以实现已经定于好的协议。

    bool flag1=[child conformsToProtocol:@protocol(NewProtocol)];
            NSLog(@"%d",flag1);
            
            bool flag2=[child conformsToProtocol:@protocol(MyProtocol)];
            NSLog(@"%d",flag2);
            
            bool flag3=[child conformsToProtocol:@protocol(ProtocolCom)];
            NSLog(@"%d",flag3);
    判断某个类是否遵循协议

        从以上代码可以看得出,conformsToProtocol 方法用于判断某个类是否遵循某个协议,返回值为bool类型,即使协议是通过"继承"过来的也可以。

      本文到此结束,学习笔记可能有诸多问题,望请牛人勿喷,菜鸟的学习需要鼓励!

  • 相关阅读:
    oracle里的tns是什么意思
    什么是联机分析处理(OLAP)
    JDBC和ODBC
    mysql 乱码
    eclipse常用快捷键和插件
    数仓项目01:准备工作
    github、maven、idea初始化一个项目
    数仓项目02:集群搭建
    数仓项目03:数据采集层(Flume+Kafka)
    Java Swing 日期控件(转载)
  • 原文地址:https://www.cnblogs.com/qingyuan/p/3612474.html
Copyright © 2020-2023  润新知