您的位置:首页 > 编程语言

类别的扩展

2015-07-01 16:38 330 查看

类别的扩展 续

利用类别分散实现代码

在大型的项目中,一个类的实现可能非常大,并且 .m 文件不能分离.但是使用类别可以将一个类的实现分散且有规律的组织在不同的文件中.还可以将一个类的实现分散到不同的框架中.

编程人员可以更加容易阅读代码并实现多人合作编码

版本管理降低冲突

维护人员跟容易理解代码

在代码的头文件中,假如有如下这么多的成员变量,也就需要相应的 setter, 和 getter 方法

#import <Foundation/Foundation.h>

@interface Things : NSObject
{
NSUInteger thing1;
NSUInteger thing2;
NSUInteger thing3;
NSUInteger thing4;
NSUInteger thing5;
}

- (void)resetAllValue;
- (void)print;

- (void)setThing1:(NSUInteger)thing1;
- (NSUInteger)thing1;

- (void)setThing2:(NSUInteger)thing2;
- (NSUInteger)thing2;

- (void)setThing3:(NSUInteger)thing3;
- (NSUInteger)thing3;

- (void)setThing4:(NSUInteger)thing4;
- (NSUInteger)thing4;

- (void)setThing5:(NSUInteger)thing5;
- (NSUInteger)thing5;

@end


这样相应的. m 文件就会繁琐到不行,这才是5个变量,假如是100个,需要许多人来完成,总不能让每个人都拿着核心文件吧,于是把它们分散开非常有必要,而类别给我们提供了一种这样的机制,只需要一个总的实现文件 .m,然后把其中部分方法分散到其类别文件中去实现.如下, 头文件Things.h文件要修改代码如下:

@interface Things : NSObject
{
NSUInteger thing1;
NSUInteger thing2;
NSUInteger thing3;
NSUInteger thing4;
NSUInteger thing5;
}

- (void)resetAllValue;
- (void)print;
//类的扩展如下
@interface Things (thing1)
- (void)setThing1:(NSUInteger)thing1;
- (NSUInteger)thing1;
@end

@interface Things (thing2)

- (void)setThing2:(NSUInteger)thing2;
- (NSUInteger)thing2;
@end

@interface Things (thing3)

- (void)setThing3:(NSUInteger)thing3;
- (NSUInteger)thing3;
@end

@interface Things (thing4)
- (void)setThing4:(NSUInteger)thing4;
- (NSUInteger)thing4;
@end

@interface Things (thing5)

- (void)setThing5:(NSUInteger)thing5;
- (NSUInteger)thing5;
@end


实现文件 Things.m 的内容只需要核心的方法,其余让其扩展类别去做:

#import "Things.h"

@implementation Things

- (void)print
{
NSLog(@"%ld,%ld,%ld,%ld,%ld",self.thing1,self.thing2,self.thing3,self.thing4,self.thing5);
}

- (void)resetAllValue
{
self.thing1 = 100;
self.thing2 = 200;
}

@end


其余具体实现,即需要好多人做的部分,给他们分开,下面举一个 Things+Thing1.m 文件

#import "Things.h"

@implementation Things (Thing1)

- (void)setThing1:(NSUInteger)t
{
thing1 = t;

}

- (NSUInteger)thing1
{
return thing1;
}

@end


通过类别创建前向引用和方法声明

Cocoa 没有真正的私有方法,但是如果你知道对象支持的某个方法的名称,就算是该对象所在的了类的接口中没有声明这个方法,也可以调用它.因为可以使用类别告诉编译器此方法已经声明过了.

越狱项目中常常使用类别的这个功能,完成调用私有 API.

响应选择器

所谓响应选择器,可以理解为方法的类型.

响应选择器也是 Objective-C 运行时的特性.

可以通过选择器来判断一个对象是否能够执行某一个方法或者说测试一个对象能否响应指定的消息.

响应选择器既然可以理解为方法或者说消息的类型所以它可以作为方法的参数传递使用.也可以作为实例变量被储存,非常灵活.

使用@ selector() 编译器指令来指定选择器,圆括号里是具体的方法名.如:

@selector(setEngine:)
@selector(setTire:atIndex)


选择器的类型关键字: SEL

(BOOL)respondsToSelector:(SEL)aSelector;// 使用此方法可以判断某一对象是否可以执行指定的方法.

举例代码:

4000
QYCar *car = [[Car alloc] init];
if([car respondsToSelector:@selector(setEngine:)]){
NSLog(@"hihi");
}


委托和非正式协议

所谓委托,其实就是一个对象有另一个对象请求执行某些操作的技术实现.

所谓非正式协议,其实就是创建一个 NSObject 的类别.

下面,我就用一个简单的例子来实现非正式协议实现委托

第一步,创建名 QYXiaoMing的类继承自NSObject 类,在创建一个 QYXiaoHong 的类,来实现一个这样的功能:

小明学习累了,想让小红在他睡着后某段时间后再把他叫起来,这时候小红叫小明这个动作就是一个委托 .具体代码如下:

QYXiaoMing.h 的内容

#import <Foundation/Foundation.h>

@interface QYXiaoMing : NSObject

//小明学习累了,有学习的行为
- (void)startSleep:(NSUInteger) time;

@end//QYXiaoMing.h


QYXiaoMing.m 的内容

#import "QYXiaoMing.h"
#import "QYXiaoHong.h"
@implementation QYXiaoMing

- (void)startSleep:(NSUInteger)time
{
NSLog(@"Sleep...");
QYXiaoHong *xiaohong = [[QYXiaoHong alloc] init];
[xiaohong call:time];
}

@end//QYXiaoMing.m


头文件QYXiaoHong.h

#import <Foundation/Foundation.h>

@interface QYXiaoHong : NSObject

- (void)call:(NSUInteger)time;

@end//QYXiaoHong.h


具体实现QYXiaoHong.m

#import "QYXiaoHong.h"

@implementation QYXiaoHong

- (void)call:(NSUInteger)time
{
//需要在指定的时间里把小明叫起来(计时器的用法)
[NSTimer  scheduledTimerWithTimeInterval:time target:self selector:@selector(callXiaoMing) userInfo:nil repeats:NO];
}

@end //QYXiaoHong.m


类别头文件NSObject+CallXiaoMing.h

#import <Foundation/Foundation.h>

@interface NSObject (CallXiaoMing)

- (void)callXiaoMing;

@end


类别实现文件NSObject+CallXiaoMing.m

#import "NSObject+CallXiaoMing.h"

@implementation NSObject (CallXiaoMing)

- (void)callXiaoMing
{
NSLog(@"lalala,don't sleep!");
}
@end


main.m 的代码

#import <Foundation/Foundation.h>

#import "QYXiaoMing.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
QYXiaoMing *xiaoming = [[QYXiaoMing alloc] init];
[xiaoming startSleep:5];//5是5秒

//要求程序运行到这里,不能结束, 是为了让显示的时间循环显示下
[[NSRunLoop currentRunLoop] run];
}
return 0;
}//main.m
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息