一、类别(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
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;
}
**:协议的相关案例后面的博文中会继续分享。= =