01).分类Categroy
又称扩展类,在不改变原来的类内容的基础上,为类增加一些方法。
01>.分类的使用注意
(1)分类只能增加方法(包括类方法和对象方法),不能增加成员变量
(2)在分类方法的实现中可以访问原来类中的成员变量;
(3)分类中可以重新实现原来类中的方法,但是会覆盖掉原来的方法,导致原来的方法无法再使用(警告);
(4)方法调用的优先级:分类->原来的类->父类,若包含有多个分类,则最后参与编译的分类优先;
(5)在很多的情况下,往往是给系统自带的类添加分类,如NSObject和NSString,因为有的时候,系统类可能并不能满足我们的要求。
(6)在大规模的应用中,通常把相应的功能写成一个分类,可以有无限个分类,对原有类进行扩充,一般分模块写,一个模块一个分类。
(7) 分类中可以写@property 但只能生成setter getter 的声明,实现得自己写
(8) 本类中的真私有属性,分类是不能访问的,但是可以通过相应的getter setter方法来访问
(9) 分类中可以存在与本类同名的方法,不论是否引入分类,调用的都是分类的方法
(10)与继承不同,不可在扩展方法中通过super调用原始方法.
举例:人类固有方法->吃饭,现在给人增加一个->学习的方法
//定义类HMPerson.h
#import <Foundation/Foundation.h>
@interface HMPerson : NSObject
-(void)eat;
@end
//HMPerson.m
#import "HMPerson.h"
@implementation HMPerson
-(void)eat{
NSLog(@"人在吃东西");
}
@end
//扩展HMPerson+study.h
#import "HMPerson.h"
@interface HMPerson (study)
- (void)study;
+ (void)study;
@end
//HMPerson+study.m
#import "HMPerson+study.h"
@implementation HMPerson (study)
- (void)study
{
NSLog(@"人在学习,对象方法");
}
+ (void)study
{
NSLog(@"人在学习,类方法");
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "HMPerson.h"
#import "HMPerson+study.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
HMPerson *p = [[HMPerson alloc] init];
[p eat];
[p study];//分类中的对象方法
[HMPerson study];//分类中的类方法,开发中常用
}
return 0;
}
02).非正式协议(informal protocol)与正式协议(formal protocol)
- 非正式协议(informal protocol):使用类别category来实现,所谓的非正式协议就是类别,即凡是NSObject或其子类的类别,都是非正式协议。
举例:写一个方法计算当前字符串对象中有多少个阿拉伯数字.
//声明NSString+countFunction.h
#import <Foundation/Foundation.h>
@interface NSString (countFunction)
- (NSUInteger)numberOfCount;
@end
//实现NSString+countFunction.m
#import "NSString+itheima.h"
@implementation NSString (itheima)
//注:不需要参数.因为当前对象就是字符串.
- (NSUInteger)numberOfCount
{
//计算当前字符串对象中有多少个阿拉伯数字.
NSUInteger count = 0;
//遍历当前这个字符串对象.
for(int i = 0; i < self.length; i++)
{
unichar ch = [self characterAtIndex:i];
if(ch >= '0' && ch <= '9')
{
count++;
}
}
return count;
}
@end
//测试非正式协议main.m
#import <Foundation/Foundation.h>
#import "NSString+itheima.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *str = @"1dihnwdiwhifn23ifnr2ieh3n2ie4n2in4ri3nrt3ibni3nt5";
NSUInteger count = [str numberOfCount];
NSLog(@"count = %lu",count);
}
return 0;
}
- 正式协议(formal protocol):指的是一个以@protocol方式命名的方法列表,与非正式协议相比不同的是,它要求显示的采用协议。
//协议–begain
//protocol协议 HMProtocol.h
#import <Foundation/Foundation.h>
@protocol HMProtocol <NSObject>
- (void)work;
//定义必须实现的方法@required
@required
-(void)requiredFunction;
//定义可选的方法@optional
@optional
-(void)optionalFunction;
@end
//人类声明HMPerson.h
#import <Foundation/Foundation.h>
#import "HMProtocol.h"//这里需要把协议的头文件引进来
@interface HMPerson : NSObject<HMProtocol>//这里必须遵守协议
- (void)eat;
@end
//人类实现HMPerson.m
#import "HMPerson.h"
@implementation HMPerson
- (void)eat
{
NSLog(@"人在吃");
}
- (void)work//实现协议里面的方法
{
NSLog(@"人在工作");
}
//实现协议中必须的方法:required方法
-(void) requiredFunction
{
NSLog(@"RequiredFunction PS: 我是协议中required方法,不实现我会有警告!");
}
//实现协议中可选的方法,不实现不会有警告
-(void) optionalFunction
{
NSLog(@"OptionalFunction PS: 我是protocol中得可选协议,不实现我,不会有警告!");
}
@end
03).延展Extension
是1个特殊的分类
匿名;只有声明,没有实现;和本类共享1个实现
01>.语法
@interface 本类名 ()
@end
延展的第一种形式(独立出来,不常用)
举例:人已有打招呼方法,请延展跑步方法
//声明类HMPerson.h
#import <Foundation/Foundation.h>
@interface HMPerson : NSObject
@property(nonatomic,strong)NSString *name;
@property(nonatomic,assign)int age;
- (void)sayHi;
@end
//扩展HMPerson_newFunction.h 有独立头文件
#import "HMPerson.h"
@interface HMPerson ()
@property(nonatomic,assign)int num2;
- (void)run;
@end
//实现HMPerson.m
#import "HMPerson.h"
#import "HMPerson_newFunction.h"
@implementation HMPerson
- (void)run
{
NSLog(@"piapia的跑");
}
- (void)sayHi
{
NSLog(@"大家好,我来了!");
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "HMPerson.h"
#import "HMPerson_newFunction.h"//需要把延展的头文件引入进来
int main() {
@autoreleasepool {
HMPerson *p = [[HMPerson alloc] init];
[p run];//调用延展里面的方法
p.num2 = 20;//访问延展里面的属性
}
return 0;
}
延展的第二种形式(写在.m文件中,开发常用)
//声明类HMPerson.h
#import <Foundation/Foundation.h>
@interface HMPerson : NSObject
@property(nonatomic,strong)NSString *name;
@property(nonatomic,assign)int age;
- (void)sayHi;
@end
#import "HMPerson.h"
//实现HMPerson.m
//这是延展(不单独出去,直接写在.m文件里面)
@interface HMPerson ()
@property(nonatomic,assign)int num2;
- (void)run;
@end
@implementation HMPerson
- (void)run
{
NSLog(@"piapia的跑");
}
- (void)sayHi
{
NSLog(@"大家好,我来了!");
[self run];//放在.m文件的延展是私有的,只能在当前类中使用
self.num2 = 20;//放在.m文件的延展是私有的,只能在当前类中访问
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "HMPerson.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
HMPerson *p = [[HMPerson alloc] init];
[p run];//这里调用会出错,因为放在.m文件的延展是私有的
p.num2 = 20;//这里访问会出错,因为放在.m文件的延展是私有的
}
return 0;
}
02>.使用注意
a.分类中只能新增方法,可以写@property 但是只会生成getter
b.延展中可以写属性
也可以写@property,会自动的生成私有属性
03>.作用
a.只能在内部访问,不能再外面访问
b.私有化类的成员
04>.注意
a.属性需要被私有化