一. Category
不同的翻译名称:分类、类别、类目(一般叫分类)
分类是Objective-C特有的语法,其他语言没有。
作用
(1).可以不用修改一个类的基础上扩充这个类
(2).一个庞大的类可以分模块开发,可以有多人开发,方便团队合作注意
(1).只能增加方法,不能增加成员变量
(2).在分类中使用@property只会生成方法声明
(3).分类可以访问原来类的成员变量
(4).如果分类和原来类出现同名的方法,优先调用分类中的方法,原来类中的同名方法会被忽略。分类的编译顺序:多个分类有同名的方法,则执行最后编译的文件。
注意:不推荐写与原有类同名的方法名
分类名一般写分类要实现的功能或编程者的名字
当给Foundation框架中的类写分类时,头文件名字为“原类名+分类名.h”,实现文件名字为“原类名+分类名.m”
当给自己写的类分模块时,可以把分类的声明都写在原类声文件,把分类的实现写在原有类的实现文件中
如下代码:
----------下面是Cat.h文件内容
#import <Foundation/Foundation.h>
@interface Cat : NSObject
@property (nonatomic,copy) NSString *colour;
- (void)eat;
- (void)play;
@end
@interface Cat (skill)
- (void)catchAMouse;
@end
----------下面是Cat.m文件内容
#import "Cat.h"
@implementation Cat
- (void)eat {
NSLog(@"吃吃吃...");
}
- (void)play{
NSLog(@"玩玩玩...");
}
@end
@implementation Cat (skill)
- (void)catchAMouse {
NSLog(@"抓老鼠咯...");
}
@end
二. Extension
不同的翻译名称:扩展、延展
类扩展就比分类少一个分类名,但括号不能少,是分类的一个特例,也称匿名分类。
作用:可以为类添加一些私有的属性(成员变量、实例变量)和方法。
一般把类扩展写在.m文件中。
格式如下:
----------下面是Cat.h文件内容
#import <Foundation/Foundation.h>
@interface Cat : NSObject
@property (nonatomic,copy) NSString *colour;
- (void)eat;
- (void)play;
@end
----------下面是Cat.m文件内容
#import "Cat.h"
@interface Cat ()
- dance;
@end
@implementation Cat
- (void)eat {
NSLog(@"吃吃吃...");
}
- (void)play{
NSLog(@"玩玩玩...");
}
- dance {
NSLog(@"跳跳跳...");
}
@end
三. Protocol
Protocol:协议
作用:用来声明一些方法,一个协议由多个方法的声明组成。
类遵守协议:一个类可以遵守一个或多个协议,任何类只要遵守了协议,就相当于拥有了协议里所有的方法声明。
注意
(1). 协议只能声明方法,不能声明属性
a. 方法声明列表中,如果没有使用任何关键字修饰协议中的方法, 那么该方法默认就是@required
b. 如果协议中的方法是@required(需要实现)的, 而遵守协议的类又没有实现该方法, 那么会报一个警告
c. 如果协议中的方法是@optional(可选实现)的, 而遵守协议的类又没有实现该方法, 那么不会报警告
d. @required和@optional仅仅使用于程序员之间交流, 并不能严格的控制某一个遵守该协议的类必须要实现该方法, 因为即便不是实现也不会报错, 只会报一个警告
(2). 父类遵守了某个协议, 那么子类也会自动遵守这个协议
(3). OC中的协议又可以遵守其它协议, 只要一个协议遵守了其它协议, 那么这个协议就会自动包含其它协议的方法声明
协议的应用场景
(1). 类型限定
a.限定协议要实现那些方法,类型限定是写在数据类型的右边的。
b.虽然在接受某一个对象的时候, 对这个对象进行了类型限定(限定它必须实现某个协议), 但是并不意味着这个对象就真正的实现了该方法. 所以每次在调用对象的协议方法时,应该用respondsToSelector:方法进行一次验证
(2). 代理设计模式及协议的编写规范
a. 一般情况下, 当前协议属于谁, 我们就将协议定义到谁的头文件中
b.协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegatec. 协议中的方法名称一般以协议的名称protocol之前的类名作为开头
d. 一般情况下协议中的方法会将触发该协议的对象传递出去
e. 一般情况下一个类中的代理属性的名称叫做 delegate
f. 当某一个类要成为另外一个类的代理的时候, 一般情况下在.h文件中用 ”@protocol 协议名称;” 告诉当前类这是一个协议;在.m文件中用#import真正的导入一个协议的声明
代码实现举例
----------下面是Man.h文件内容
#import <Foundation/Foundation.h>
@class Man;
//1.协议属于Man类,所有写到Man类的头文件中
//2.协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegate
@protocol ManProtocol <NSObject>
//3.协议中的方法名称一般以协议的名称protocol之前的类名作为开头
//4.一般情况下协议中的方法会将触发该协议的对象传递出去
- (void)manlookAfterChildren:(Man *)man;
- (void)mancook:(Man *)man;
@end
@interface Man : NSObject
//5.一般情况下一个类中的代理属性的名称叫做 delegate
@property (nonatomic,strong) id<ManProtocol> protocol;
@end
----------下面是Man.m文件内容
#import "Man.h"
@implementation Man
@end
----------下面是Woman.h文件内容
#import <Foundation/Foundation.h>
//6.当某一个类要成为另外一个类的代理的时候, 一般情况下在.h文件中用 ”@protocol 协议名称;” 告诉当前类这是一个协议
@protocol ManProtocol;
@interface Woman : NSObject <ManProtocol>
@end
----------下面是Woman.m文件内容
#import "Woman.h"
//7.在.m文件中用#import真正的导入一个协议的声明
//导入Man.h是因为,里面存在ManProtocol协议,以及有Man的声明
#import "Man.h"
@implementation Woman
- (void)manlookAfterChildren:(Man *)man {
NSLog(@"%@ 宝贝乖乖,快睡觉觉...",man);
}
- (void)mancook:(Man *)man {
NSLog(@"%@ 热爱做饭!",man);
}
@end