OutMan——Objective-C中分类、延展、非正式协议和协议

来源:互联网 发布:csgo控制台优化 编辑:程序博客网 时间:2024/05/22 07:02

分类(category:分类、类别、类目)

一、分类的作用
        分类的作用是:在不改变原来类的基础上,可以增加一些方法

二、分类的使用注意
1. 分类只能增加方法,不能增加成员变量(也不能使用@property生成原来类中没有的成员变量)
2. 分类方法实现中可以访问原来类中声明的成员变量
3. 分类可以重新实现原来类中的方法,但会覆盖掉原来的方法,会导致原来的方法没法再使用
4. 方法调用的优先级:分类(最后参与编译的分类优先)—>原来类—>父类
5. 分类增加的方法能被子类继承

三、如何给某个类分类
这里写图片描述
这里写图片描述

四、使用分类的目的
1. 对现有的类进行扩展:比如你可以扩展Cocoa touch框架中的类,你在分类中增加的方法会被子类继承,而且在运行时跟其他方法没有区别
2. 作为子类的代替手段:不需要定义和使用一个子类,可以通过分类直接向已有的类里增加方法
3. 对类中的方法归类:利用分类把一个庞大的类划分为多个小块来分别进行开发,从而更好的对类中方法进行更新和维护

五、分类的代码分析
(1)Person类的设计
                                                                     Person.h文件

#import <Foundation/Foundation.h>@interface Person : NSObject{    int _age;}@property int age;   // 年龄// run方法的声明- (void)run;// test方法的声明- (void)test;@end

                                                                     Person.m文件

#import "Person.h"@implementation Person// run方法的实现- (void)run{    NSLog(@"%d岁的人在奔跑", _age);}// test方法的实现- (void)test{    NSLog(@"Person----->test");}@end

(2)Person类的分类Person+Eat类的设计
                                                                     Person+Eat.h文件

#import "Person.h"@interface Person (Eat)// eat方法的声明- (void)eat;@end

                                                                     Person+Eat.m文件

#import "Person+Eat.h"@implementation Person (Eat)// eat方法的实现- (void)eat{    NSLog(@"%d岁的人在吃东西", _age);}// test方法的实现- (void)test{    NSLog(@"Person+Eat----->test");}@end

(3)Person类的分类Person+Jump类的设计
                                                                     Person+Jump.h文件

#import "Person.h"@interface Person (Jump)// jump方法的声明- (void)jump;@end

                                                                     Person+Jump.m文件

#import "Person+Jump.h"@implementation Person (Jump)// jump方法的实现- (void)jump{    NSLog(@"%d岁的人在跳", _age);}// test方法的实现- (void)test{    NSLog(@"Person+Jump----->test");}@end

(4)main.m文件
这里写图片描述
-设计注意:
1. 分类可以重新实现原来类中的方法,但会覆盖掉原来的方法,会导致原来的方法没法再使用
2. 当调用[p test]的时候,为什么打印的是Person+Eat—–>test?
方法调用的优先级:分类(最后参与编译的分类优先)—>原来类—>父类
3. 如何查看编译顺序
这里写图片描述
        从图中可以看出,最后参与编译的分类是Person+Eat这个分类,所以当调用[p test]的时候,打印的是Person+Eat—–>test

延展(扩展、延展类别)

一、延展的概念
        延展类别称为扩展(Extension)又称为延展,延展(Extension)是分类(category)的一个特例,其名字为匿名(为空),并且新添加的方法一定要予以实现(分类则没有这个限制)
        延展其实就是特殊的分类,这种写法的分类也叫匿名分类,所谓的延展,其实就是为一个类添加额外的原来没有的变量、方法或合成属性

二、延展的特点
1. 可以在延展中定义成员变量
2. 不能使用@implementation 类名()实现延展的方法
3. 可以在延展中定义私有的成员变量和方法

三、如何给某个类延展
这里写图片描述
这里写图片描述

四、延展和分类的区别
1. 分类中只能增加方法
2. 延展中不仅可以增加方法,还可以增加成员变量(或者合成属性),只是该变量默认是私有类型的(作用范围只能在自身类,而不是子类或其他地方)
3. 延展中声明的方法没有被实现,编译器会报警告,但是分类中的方法没有被实现,编译器是不会有任何警告的,这是因为延展是在编译阶段被添加到类中,而分类实在运行时添加到类中
4. 延展不能像分类那样,拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现
5. 定义在.m文件中的延展方法为私有的,定义在.h文件中的延展方法为公有的,延展是在.m文件中声明私有方法的非常好的方式

五、延展的代码实现
(1)Person类的设计
                                                                     Person.h文件

#import <Foundation/Foundation.h>@interface Person : NSObject@property int age;   // 年龄// run方法的声明- (void)run;@end

                                                                     Person.m文件

#import "Person.h"#import "Person_Eat.h"@implementation Person// run方法的实现- (void)run{    NSLog(@"%d岁的人在奔跑", _age);}// eat方法的实现- (void)eat{    NSLog(@"名字是%@,%d岁的正在吃", _name, _age);}@end

(2)Person类的延展Person_Eat类的实现
                                                                     Person+Eat.h文件

#import "Person.h"@interface Person ()@property NSString *name;   // 姓名// eat方法的声明- (void)eat;@end

(3)main.m文件
这里写图片描述
-设计注意:
1. 延展中不仅可以增加方法,也可以增加成员变量或者合成属性),只是该变量默认是私有类型的(作用范围只能在自身类,而不是子类或其他地方)

非正式协议

一、非正式协议概念
        所谓的非正式协议:凡是NSObject的分类或其子类Foundation框架中的类的分类,都是非正式协议

二、非正式协议的实现代码:
        设计要求:给NSString增加一个类方法,计算某个字符串中阿拉伯数字的个数,给NSString增加一个对象方法,计算某个字符串中阿拉伯数字的个数
(1)非正式协议的设计
                                                                     NSString+CountNumber.h文件

#import <Foundation/Foundation.h>@interface NSString (CountNumber)// 计算字符串中数字个数方法的声明+ (int)countNumber:(NSString *)aString;// 计算字符串中数字个数方法的声明- (int)countNumber;@end

                                                                     NSString+CountNumber.m文件

#import "NSString+CountNumber.h"@implementation NSString (CountNumber)// 计算字符串中阿拉伯数字个数方法的实现+ (int)countNumber:(NSString *)aString{    int count = 0;    for(int i=0; i<aString.length; i++)    {        // 取出字符串中对应index位置的字符        unichar c = [aString characterAtIndex:i];        // 如果这个字符是阿拉伯数字        if (c>='0' && c<='9')        {            count++;        }    }    return count;}// 计算字符串中阿拉伯数字个数方法的实现- (int)countNumber{    int count = 0;    for(int i=0; i<self.length; i++)    {        // 取出字符串中对应index位置的字符        unichar c = [self characterAtIndex:i];        // 如果这个字符是阿拉伯数字        if (c>='0' && c<='9')        {            count++;        }    }    return count;}@end

(2)main.m文件
这里写图片描述
-设计注意:
1. for循环中,通过length方法来获取字符串的长度
2. 通过调用字符串的对象方法来获取对应index位置的字符,然后再进行判断当前字符是否是阿拉伯数字
3. if (c>=’0’ && c<=’9’)中‘0’和‘9’必须要加单引号,不加单引号是ASCII码值0和9,而不是字符0和9

协议

一、基本用途
1. 可以用来声明一大堆方法(不能声明成员变量)
2. 只要某个类遵守了这个协议,就相当于拥有了这个协议中所有的方法声明
3. 只要父类遵守了某个协议,就相当于子类也遵守了

二、格式
(1)协议的编写
@protocol 协议名称
// 方法列表
@end
(2)某个类遵守协议
@interface 类名:父类<协议名称>
@end

三、如何创建协议
这里写图片描述
这里写图片描述

四、协议中的关键字
        协议中有2个关键字可以控制方法是否要实现(默认是@required),在大多数情况下,用途在于程序员之间的交流
@required:这个方法必须要实现(若不实现,编译器会发出警告)
@optional:这个方法不一定要实现

五、协议之间的遵守、基协议
(1)协议遵守协议
1. 一个协议可以遵守其他多个协议,多个协议之间用逗号隔开
2. 一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明
3. 格式:
@protocol 协议名称<协议1,协议2…>
@end
(2)基协议
1. NSObject是一个基类,最根本的类,任何其他类都最终要继承它
2. 其实还有个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议
3. NSObject协议中声明了很多最基本的方法,比如description、retain、release等
4. 建议每个新的协议都要遵守NSObject协议

六、Protocol限制对象类型
(1)要求obj保存的对象必须是遵守MyProtocol这个协议

NSObject<MyProtocol> *obj = [[Person alloc] init];

(2)要求obj保存的对象必须遵守MyProtocol协议并且继承了Person类

Person<MyProtocol> *obj = [[Person alloc] init];

七、协议的提前声明
1. @protocol 协议名称;提前声明
2. 当使用到这个协议里面的东西的时候,再#import这个协议的头文件
3. 在mian.m文件中调用协议中的方法时,也需要#import这个协议的头文件

八、协议的代码实现
(1)RunProtocol协议的设计
                                                                     RunProtocol.h文件

#import <Foundation/Foundation.h>@protocol RunProtocol <NSObject>// run方法的声明- (void)run;@end

-设计注意:
1. 协议中的方法声明默认是@required(需要实现的)

(2)JumpAndSingProtocol协议的设计
                                                                     JumpAndSingProtocol.h文件

#import <Foundation/Foundation.h>@protocol JumpAndSingProtocol <NSObject>@required// jump方法的声明- (void)jump;@optional// sing方法的声明- (void)sing;@end

-设计注意:
1. @required:这个方法必须要实现(若不实现,编译器会发出警告)
2. @optional:这个方法不一定要实现

(3)EatProtocol协议的设计
                                                                     EatProtocol.h文件

#import <Foundation/Foundation.h>#import "JumpAndSingProtocol.h"#import "RunProtocol.h"@protocol EatProtocol <NSObject, JumpAndSingProtocol, RunProtocol>// eat方法的声明- (void)eat;@end

-设计注意:
1. 一个协议可以遵守其他多个协议,多个协议之间用逗号隔开
2. 一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明
3. 格式:
@protocol 协议名称<协议1,协议2…>
@end

(4)Person类的设计
                                                                     Person.h文件

#import <Foundation/Foundation.h>#import "EatProtocol.h"@interface Person : NSObject<EatProtocol>@end

                                                                     Person.m文件

#import "Person.h"@implementation Person// eat方法的实现- (void)eat{    NSLog(@"Person在吃");}// jump方法的实现- (void)jump{    NSLog(@"Person在跳");}// run方法的实现- (void)run{    NSLog(@"Person在跑");}@end

-设计注意:
1. @required:这个方法必须要实现(若不实现,编译器会发出警告)
这里写图片描述
2. @optional:这个方法不一定要实现(例:sing方法不实现也没有关系)

(5)main.m文件
这里写图片描述


                                        —— 如果您有不同的见解,请随时指出,期待与您的交流!——


0 0