天天看点

【Objective-C】类别(拓展类)、协议

一、类别(Category)简介

 OC中类别功能强大,它能够在不使用继承的情况下向现有的类添加新的方法。特别是在没有类的源代码的情况下,通过使用类别依然能够向该类添加新的方法。

 类别的主要有两个作用,一是向类添加新的方法以拓展类的功能,二时将类的实现部分分布发哦多个文件中。

二、声明类别并实现类别方法

1. 类别的声明与实现的格式如下

#import "目标类名.h"

@interface 目标类名 (类别名称)

// 方法声明区

@end


@implementation 目标类名 (类别名称)

// 方法实现区

@end
           

其实类别的声明与实现格式与类的声明和实现格式类似。区别就是类别声明后面会加上小括号,而类接口声明没有小括号。方法声明区中给出了类别中的方法声明,这些方法会附加到目标类中。注意:在附加之后这些方法与类的其它方法没有任何区别,他们也能够访问类的成员变量,或是继承到目标类的子类中。但是,如果目标类和类别都定义了一个签名完全一样的方法,则类别中的方法会替换类中定义的方法。如果有两个类别都定义了一个签名完全一样的方法,则调用哪一个方法是不用确定的。另外类中只能定义方法,不能定义成员变量。

2. 拓展类的功能:

    有时候根据需要,比如说一个项目有不同的模块,要分配给不同的人做。这时候就可以使用类别,我们可以定义多个附加到目标类的类别,并在该类别中实现需要实现的方法。

新建文件---oc file---类名、file type、附加的类名称

#import "Student.h"   //导入这个文件是位了要知道目标类中有哪些方法
//#import <Foundation/Foundation.h>     //不需要导入这个文件了

// ()代表着一个分类
// ()中的Test代表着分类的名称
// 不使用@class是因为“分类”是给原类拓展一些方法

@interface Student (Test)

- (void)test2;

@end
           
#import "Student+Test.h"

@implementation Student (Test)

- (void)test2 {
    NSLog(@"这个代表调用的test2");
    
}


@end
           
【Objective-C】类别(拓展类)、协议

3. 拆分类的实现:

    除了拓展类的行为之外,类别还有一个作用就是将类的实现分成若干部分。

三、协议(代理)--- 只有声明.h没有实现.m,需要其他的类去实现

 oc中的协议与java、c#中的借口以及c++中的抽象类相类似,用于定义公共接口,并承诺类需要实现协议中规定的方法。使用协议中最大的好处就是它能够有效拓展程序的功能。比如说:,通用串行总线(Universal Serial Bus, USB)就是一个协议,它能够让计算机周边设备连接标准化。现在的计算机都配备了USB接口,这样能够有效拓展计算机的功能。USB协议定义了接口的尺寸、电压、电流大小等规范,只要设备符合USB协议就可以介入到计算机中使用。至于设备的具体作用可以由厂家自己进行设计规划。

 java、c#接口、c++抽象类要求实现它的非抽象类必须实现它规定的方法。objective-c中的协议更加灵活,他可以规定哪些方法必须实现,那些方法可以有选择性的地实现。

1. 简介:

    1. Protocol:就是一个用途,用来声明一大堆方法(不能声明成员变量),不能写实现;

    2. 只要某个类遵循了这个协议,就拥有了这个协议中的所用方法;

    3. 只要父类遵守某个协议,那么子类也遵循;

    4. Protocol声明的方法可以让任何类去实现,protocol就是协议;

    5. OC不能继承多个类(单继承)(:),但是能够遵守多个协议。(<>)

    6. 基协议:<NSObject>是基协议,是最根本的协议,其中声明了很多基本的方法;

    7. 协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明;

2. 声明协议

    关键字Protocal,和类的外部接口声明类似,协议定义在@protocol与@end指令之间。@protocol后接协议名称。并使用@required与@optional规定哪些方法必须由采用该协议的类实现,哪些方法可以有选择性地实现,默认为@required(必须要实现)。

格式:

@protocol 协议名 <父协议>

定义方法

@end

注:定义协议的关键字是@protocol,同时协议也是可以继承父协议的。

创建一个协议:

#import <Foundation/Foundation.h>

// MyProtocol就是协议,这个协议遵守基协议<NSObject>
@protocol MyProtocol <NSObject>
// 在协议中可以声明很多有用的方法
// @property int age; 在协议中不能声明成员变量,只能是声明方法,也不能实现方法
@required
// @required关键字主要用于程序员之间的交流,要求实现
- (void)pint;
- (void)haha;
@end

@interface MyProtocol : NSObject

@end
           

遵守协议:

#import <Foundation/Foundation.h>
#import "MyProtocol.h"
// 在类的声明中加入协议的头文件

// Person类的声明,这个类继承了NSObject类,遵守MyProtocol协议
@interface Person : NSObject <MyProtocol>

@end
           

或者按照下面的实现:

#import <Foundation/Foundation.h>
// #import "MyProtocol.h"
// 在类的声明中加入协议的头文件

// 方式二使用一种方式,与前面将的@class前向声明功能一样;在.m文件中在进行导入也是可以
@protocol MyProtocol;

// Person类的声明,这个类继承了NSObject类,遵守MyProtocol协议
@interface Person : NSObject <MyProtocol>

@end
           

完成协议中声明的方法的实现:

#import "Person.h"

@implementation Person
// 在这里进行遵守的协议里所声明的方法的实现

- (void)pint {
    NSLog(@"nihao!");
}

- (void)haha {
    NSLog(@"nibuhao!");
    
}

@end
           

测试程序:

#import <Foundation/Foundation.h>
#import "Person.h"
#import "MyProtocol.h"

int main(int argc, const char *argv[])
{
    @autoreleasepool {
        Person *per = [[[Person alloc] init] autorelease];
        [per pint];
        [per haha];
    }
}

           

3. 注意点

  1.协议的定义

     @protocol 协议名称 <NSObject>

     //方法声明列表

     @end;

  2.如何遵守协议

  (1)类遵守协议

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

     @end

  (2)协议遵守协议

    @protocol 协议名称 <其他协议名称>

    @end;

  3.协议方法声明中的关键字

  (1)required (默认)要求实现,若没有实现则警告但不报错

  (2)Optional 不要求实现

  4.定义变量时遵守协议的限制(只能是对象)

     类名<协议名称> *变量名    NSObject<.Myprotocol> *obj;

     Id  <协议名称>  变量名   id  <.Myprotocol> obj1;

  5.Property中声明的属性也可以做遵守协议的限制

     @property (nonatomic ,strong ) 类名<协议名称> *属性名;

     @property (nonatomic ,strong ) id<协议名称>  属性名;

  6.补充:协议本身写在头文件中,但也可以定义在任何地方。当这个协议只有这个类使用遵守时,一般把协议写在这个类里面(同一文件),当这个协议需要多个类去实现时,就写在外边单独的文件中(新建)。

4. 实现协议

    协议定义后,需要其他类遵循(实现)协议。在类的外部接口中,可以定义其他类遵从哪些协议。类不允许继承多个类,但是类允许遵从多个协议。当某个类需要遵从多个协议时,可以在类的接口中的@interface指令后给出,协议名称必须位于尖括号内,多个协议名称之间使用逗号分开。

5. 使用协议限制对象类型与行为

    协议可以限定对象类型,并在程序的编译期间给出警告。

6. 在程序中我们跟难知道程序是否实现了协议这一功能。这时候需要我们对协议进行判断。

// conformToProtocol: 判断是否遵守了某协议
        if ([stu conformsToProtocol:@protocol(Read)]) {
            NSLog(@"对象遵守了协议");
        }
        
        // 判断是否遵守了某内容
        if (![stu respondsToSelector:@selector(haha)]) {
            NSLog(@"对象没有实现这个方法");
        }
           

7. 限制对象实现协议

// 协议限制
void demo03()
{
    // 限制它遵守协议    会报错 意思是不匹配
    // NSObject<MyProtocol> *peo = [[NSObject alloc] init];
    
    NSObject<MyProtocol> *peo = [[Person alloc] init];
    peo = nil;
    
    // id<MyProtocol> *peo1 = [[Person alloc] init];  id 就是相当于 -- 类 *
    id<MyProtocol> peo1 = [[Person alloc] init];
    peo1 = nil;
    
    
}
           

**:协议的相关案例后面的博文中会继续分享。= =

继续阅读