有关类的问题
2014-07-29 20:56
232 查看
引入动态类型后,问题随之而来。比如说在运行时如何判断一个对象是某种类型,一个对象是否支持某方法,一个对象是否是某类或是其子类的成员。幸运的是,NSObject类为我们提供了一些方法用于处理这类问题,要使用这些方法,我们需要一些铺垫。
-(BOOL) isKindOf:class-object(判断对象是否是class-object或其子类的成员)
-(BOOL) isMenberOfClass:class-object(判断对象是否是class-object的成员)
-(BOOL) respondsToSelector:selector(判断对象是否能够响应selector所指定的方法)
+(BOOL) instancesRespondToSelector:selector(判断指定的类实例是否能响应selector所指定的方法)
+(BOOL) isSubclassOfClass:class-object(判断对象是否是指定类的子类)
-(id) performSelector:selector(应用selector指定的方法)
-(id) performSelector:selector withObject:object(应用selector指定的方法,传递参数object)
-(id) performSelector:selector withObject:object1 withObject:object2(应用selector指定的方法,传递参数object1和object2)
首先介绍class方法,看下面的示例代码:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *rect=[Rectangle new];
Class cls=[rect class];
NSLog(@"%@",cls);
NSLog(@"%@",[Square class]);
}
return 0;
}
首先我们创建了一个Rectangle对象rect,之后对rect调用class方法返回一个Class类型的对象,然后打印这个cls对象的内容。而下面我们对Square类直接调用class方法,也能返回Class对象,那么编译运行,我们得到如下结果:
我们可以看到通过class方法我们可以获取当前对象的类型,使用类名来调用通常也是为了返回这个类型的对象,他们都是Class类型的对象。那么我们知道class方法的用处后就可以用于判断了,比如下面的代码:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *rect=[Rectangle new];
Square *square=[Square new];
Rectangle *rectangle=[Rectangle new];
if([rect class]==[rectangle class]){
NSLog(@"rect & rectangle is the same class");
}
if([square class]==[rect class]){
NSLog(@"square & rect is the same class");
}
}
return 0;
}
那么我们很容易就能与基础该程序的效果,请看下图所示:
下面介绍@selector指令,该指令用于一个方法名,比如@selector (alloc),它的返回值是SEL类型,这个指令所获取的SEL类型结果也是用于动态类型的一些方法的,这里我们仅仅有个感性认识即可,那么看下面的代码:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
SEL sel=@selector(setSide);
NSLog(@"SEL=%@",NSStringFromSelector(sel));
}
return 0;
}
这里我们需要将SEL结果转换成NSString类型,那么编译运行,我们会得到如下结果:
那么在后面处理动态类型的方法中,我们会看到@selector指令的具体用途。参考下面的程序:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Square *square=[Square new];
NSLog(@"%@",[square isMemberOfClass:[Square class]]?@"YES":@"NO");
NSLog(@"%@",[square isMemberOfClass:[Rectangle class]]?@"YES":@"NO");
NSLog(@"%@",[square isMemberOfClass:[NSObject class]]?@"YES":@"NO");
NSLog(@"%@",[square isKindOfClass:[Square class]]?@"YES":@"NO");
NSLog(@"%@",[square isKindOfClass:[Rectangle class]]?@"YES":@"NO");
NSLog(@"%@",[square isKindOfClass:[NSObject class]]?@"YES":@"NO");
NSLog(@"%@",[square respondsToSelector:@selector(setSide:)]?@"YES":@"NO");
NSLog(@"%@",[square respondsToSelector:@selector(setWidth:andHeight:)]?@"YES":@"NO");
NSLog(@"%@",[Square respondsToSelector:@selector(alloc)]?@"YES":@"NO");
NSLog(@"%@",[Rectangle instanceRespondToSelector:@selector(setSide:)]?@"YES":@"NO");
NSLog(@"%@",[Square instanceRespondToSelector:@selector(setSide:)]?@"YES":@"NO");
NSLog(@"%@",[Square isSubclassOfClass:[Rectangle class]]?@"YES":@"NO");
}
return 0;
}
我们先来看运行结果:
我们逐行来解释一下这个程序,isMemberOfClass : class方法用于判断对象是不是class的成员,返回值为BOOL类型,那么这里我们使用三目运算符来获取BOOL表达式的结果,NSString也是id类型的一种,那么我们使用%@来表示。很显然square对象是Square类的一个成员,而不是Rectangle类和NSObject类的成员。
isKindOfClass: class方法用于判断对象是不是class类或其子类的成员。显然square对象是Square类的成员,是Rectangle类和NSObject类的子类成员。
respondsToSelector : selector方法用于判断对象是否可以响应@selector提供的方法,那么直接看上面的结果即可,不用多说了。instanceRespondToSelector : selector方法用于判断指定的实例能否响应@selector提供的方法,那么直接看结果就行了。
这些方法我们仅仅有个感性认识即可,等后续内容使用到了再做深入了解。
我们知道运用动态类型时在程序执行过程中可能会出现异常,那么如何来处理异常呢?Objective-C中引入@try块儿来处理异常,异常处理在@catch块中进行。我们来看下面的代码:
C代码
#import "Fraction.h"
#import "Complex.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
id result;
id fractionA = [Fraction new];
[fractionA setTo:1 over:3];
id complexA=[Complex new];
[complexA setReal:10.0 andImaginary:2.3];
@try {
result=[fractionA add:complexA];
}
@catch (NSException *exception) {
NSLog(@"Caught: %@%@",exception.name,exception.reason);
}
@finally {
NSLog(@"In finally");
}
}
return 0;
}
代码使用的是我们分数和复数的项目,那么为了引发异常,我们将分数类和复数类都使用id类型来表示,显然编译器不会报错,然后我们对两个不同的对象使用add方法,这显然是不可以的,那么将代码放入@try块中,在@catch块中进行异常处理,这里我们仅仅是打印一些异常信息。在@finally块中编写不论异常是否发生,都要执行的代码,那么编译运行后,我们得到如下结果:
之后我们修改代码,不会出现异常时是这样的情况:
C代码
#import "Fraction.h"
#import "Complex.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
id result;
id fractionA = [Fraction new];
[fractionA setTo:1 over:3];
id fractionB=[Fraction new];
[fractionB setTo:10 over:18];
@try {
result=[fractionA add:fractionB];
}
@catch (NSException *exception) {
NSLog(@"Caught: %@%@",exception.name,exception.reason);
}
@finally {
NSLog(@"In finally");
}
}
return 0;
}
此时代码不会出错了,那么编译运行就得到了如下结果:
可以看到@finally块中的语句无论异常是否发生,都会执行。所以它常用来进行连接的关闭等操作。如果想主动抛异常,还可以使用@throw指令来进行,这就是更高级内容了,暂时先不涉及。因为异常处理的开销很大,特别是移动设备对资源占用很敏感,所以非必要,请不要使用异常处理。
转自:http://sarin.iteye.com/blog/1820539
-(BOOL) isKindOf:class-object(判断对象是否是class-object或其子类的成员)
-(BOOL) isMenberOfClass:class-object(判断对象是否是class-object的成员)
-(BOOL) respondsToSelector:selector(判断对象是否能够响应selector所指定的方法)
+(BOOL) instancesRespondToSelector:selector(判断指定的类实例是否能响应selector所指定的方法)
+(BOOL) isSubclassOfClass:class-object(判断对象是否是指定类的子类)
-(id) performSelector:selector(应用selector指定的方法)
-(id) performSelector:selector withObject:object(应用selector指定的方法,传递参数object)
-(id) performSelector:selector withObject:object1 withObject:object2(应用selector指定的方法,传递参数object1和object2)
首先介绍class方法,看下面的示例代码:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *rect=[Rectangle new];
Class cls=[rect class];
NSLog(@"%@",cls);
NSLog(@"%@",[Square class]);
}
return 0;
}
首先我们创建了一个Rectangle对象rect,之后对rect调用class方法返回一个Class类型的对象,然后打印这个cls对象的内容。而下面我们对Square类直接调用class方法,也能返回Class对象,那么编译运行,我们得到如下结果:
我们可以看到通过class方法我们可以获取当前对象的类型,使用类名来调用通常也是为了返回这个类型的对象,他们都是Class类型的对象。那么我们知道class方法的用处后就可以用于判断了,比如下面的代码:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *rect=[Rectangle new];
Square *square=[Square new];
Rectangle *rectangle=[Rectangle new];
if([rect class]==[rectangle class]){
NSLog(@"rect & rectangle is the same class");
}
if([square class]==[rect class]){
NSLog(@"square & rect is the same class");
}
}
return 0;
}
那么我们很容易就能与基础该程序的效果,请看下图所示:
下面介绍@selector指令,该指令用于一个方法名,比如@selector (alloc),它的返回值是SEL类型,这个指令所获取的SEL类型结果也是用于动态类型的一些方法的,这里我们仅仅有个感性认识即可,那么看下面的代码:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
SEL sel=@selector(setSide);
NSLog(@"SEL=%@",NSStringFromSelector(sel));
}
return 0;
}
这里我们需要将SEL结果转换成NSString类型,那么编译运行,我们会得到如下结果:
那么在后面处理动态类型的方法中,我们会看到@selector指令的具体用途。参考下面的程序:
C代码
#import "Square.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Square *square=[Square new];
NSLog(@"%@",[square isMemberOfClass:[Square class]]?@"YES":@"NO");
NSLog(@"%@",[square isMemberOfClass:[Rectangle class]]?@"YES":@"NO");
NSLog(@"%@",[square isMemberOfClass:[NSObject class]]?@"YES":@"NO");
NSLog(@"%@",[square isKindOfClass:[Square class]]?@"YES":@"NO");
NSLog(@"%@",[square isKindOfClass:[Rectangle class]]?@"YES":@"NO");
NSLog(@"%@",[square isKindOfClass:[NSObject class]]?@"YES":@"NO");
NSLog(@"%@",[square respondsToSelector:@selector(setSide:)]?@"YES":@"NO");
NSLog(@"%@",[square respondsToSelector:@selector(setWidth:andHeight:)]?@"YES":@"NO");
NSLog(@"%@",[Square respondsToSelector:@selector(alloc)]?@"YES":@"NO");
NSLog(@"%@",[Rectangle instanceRespondToSelector:@selector(setSide:)]?@"YES":@"NO");
NSLog(@"%@",[Square instanceRespondToSelector:@selector(setSide:)]?@"YES":@"NO");
NSLog(@"%@",[Square isSubclassOfClass:[Rectangle class]]?@"YES":@"NO");
}
return 0;
}
我们先来看运行结果:
我们逐行来解释一下这个程序,isMemberOfClass : class方法用于判断对象是不是class的成员,返回值为BOOL类型,那么这里我们使用三目运算符来获取BOOL表达式的结果,NSString也是id类型的一种,那么我们使用%@来表示。很显然square对象是Square类的一个成员,而不是Rectangle类和NSObject类的成员。
isKindOfClass: class方法用于判断对象是不是class类或其子类的成员。显然square对象是Square类的成员,是Rectangle类和NSObject类的子类成员。
respondsToSelector : selector方法用于判断对象是否可以响应@selector提供的方法,那么直接看上面的结果即可,不用多说了。instanceRespondToSelector : selector方法用于判断指定的实例能否响应@selector提供的方法,那么直接看结果就行了。
这些方法我们仅仅有个感性认识即可,等后续内容使用到了再做深入了解。
我们知道运用动态类型时在程序执行过程中可能会出现异常,那么如何来处理异常呢?Objective-C中引入@try块儿来处理异常,异常处理在@catch块中进行。我们来看下面的代码:
C代码
#import "Fraction.h"
#import "Complex.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
id result;
id fractionA = [Fraction new];
[fractionA setTo:1 over:3];
id complexA=[Complex new];
[complexA setReal:10.0 andImaginary:2.3];
@try {
result=[fractionA add:complexA];
}
@catch (NSException *exception) {
NSLog(@"Caught: %@%@",exception.name,exception.reason);
}
@finally {
NSLog(@"In finally");
}
}
return 0;
}
代码使用的是我们分数和复数的项目,那么为了引发异常,我们将分数类和复数类都使用id类型来表示,显然编译器不会报错,然后我们对两个不同的对象使用add方法,这显然是不可以的,那么将代码放入@try块中,在@catch块中进行异常处理,这里我们仅仅是打印一些异常信息。在@finally块中编写不论异常是否发生,都要执行的代码,那么编译运行后,我们得到如下结果:
之后我们修改代码,不会出现异常时是这样的情况:
C代码
#import "Fraction.h"
#import "Complex.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
id result;
id fractionA = [Fraction new];
[fractionA setTo:1 over:3];
id fractionB=[Fraction new];
[fractionB setTo:10 over:18];
@try {
result=[fractionA add:fractionB];
}
@catch (NSException *exception) {
NSLog(@"Caught: %@%@",exception.name,exception.reason);
}
@finally {
NSLog(@"In finally");
}
}
return 0;
}
此时代码不会出错了,那么编译运行就得到了如下结果:
可以看到@finally块中的语句无论异常是否发生,都会执行。所以它常用来进行连接的关闭等操作。如果想主动抛异常,还可以使用@throw指令来进行,这就是更高级内容了,暂时先不涉及。因为异常处理的开销很大,特别是移动设备对资源占用很敏感,所以非必要,请不要使用异常处理。
转自:http://sarin.iteye.com/blog/1820539
相关文章推荐
- 一个有关扑克牌牌型分析的问题
- 号外:有关VS.NET Beta2 7月31日过期的问题
- 四川省人事厅 四川省信息产业厅关于2004年(下半年)计算机技术与软件专业技术资格(水平)考试有关问题的通知
- 再谈和字体有关的几个问题
- 有关DNS的几个安全性问题
- 请问dudu有关图片的问题
- 四川省人事厅 四川省信息产业厅 关于2004年(上半年)计算机技术与软件专业技术资格(水平)考试有关问题的通知
- 最近在使用sps类库过程中发现了一个让我比较疑惑的问题(有关items属性的)
- 有关级联表中的约束问题?
- java中有关日期的显示问题
- Good stuff, Bruce Eckel有关Java存在的问题以及未来方向的报告
- 有关DbGrid 的问题(求救)
- [导入]有关构造方法的问题
- 有关C++界面皮肤控件的问题!!
- 有关引用以及LoadBitmap几个容易混淆的问题
- 有关录音缓冲区的问题~
- 有关DataGrid显示数据的问题
- 在asp.net中有关"弹出对话框"的问题
- 与PHP开发有关的模板问题
- java中有关日期的显示问题