LHF Objective-C语法(7)id类型、动态判断与选择器

本文介绍了Objective-C中的id类型使用方法,展示了如何通过类别扩展类功能而不使用继承,并提供了动态判断对象类型及方法响应性的示例。

1、id类型

// Complex.h============================== #import <Foundation/Foundation.h> @interface Complex : NSObject{ double real; double imageinary; } -(Complex*) initWithReal:(double) r andImageinary:(double)i; -(void)setReal:(double) r; -(void)setImaginary:(double) i; -(void)setReal:(double)r andImaginary:(double) i; -(double)real; -(double)imaginary; -(void)print; @end // Complex.h============================== #import "Complex.h" @implementation Complex -(Complex*) initWithReal:(double) r andImageinary:(double)i; { self = [super init]; if(self){ [self setReal:r andImaginary:i]; } return self; } -(void)setReal:(double) r{ real = r; } -(void)setImaginary:(double) i{ imaginary = i; } -(void)setReal:(double)r andImaginary:(double) i{ real = r; imaginary = i; } -(double)real{ return real; } -(double)imaginary{ return imaginary; } -(void)print{ NSLog(@"%f + %fi",real,imaginary); } @end // main.m============================== #import "Fraction.h" #import "Complex.h" int main(argc,const char * argv[]){ Fracion *frac = [[Fraction alloc] intiWithNumerator:3 andDenominator:5]; Complex *comp = [[Complex alloc] initWithReal:1.5 andImaginary:3.5]; id number = frac; [number print]; number = comp; [comp print]; [frc release]; [comp release]; return 0; }

number先指向frac实例,调用了他的print方法,然后指向comp实例,调用了他的print

2、动态判断与选择器

假如别人传递给你一个id,你如何动态判断这个在运行时传递过来的对象到底有没有xxx方法那?

其实NSObject中有一系列这样的方法用于动态判断,类似java的反射机制

      -(BOOL)isMemberOfClass:(Class)  clazz //判断对象是否是clazz的实例,不包含子类的实例

     -(BOOL)isKindOfClass:(Class) clazz //判断对象是否是clazz的实例或子类的实例

     -(BOOL)respondsToSelector:(SEL) selector //判断类型或对象是否能够回应某个方法,这个方法使用选择器表示

     +(BOOL)instancesRespondToSelector:(SEL) selector//判断类型所产生的实例是否能够回应某个方法,这个方法使用选择器表示

     -(id)performSelector:(SEL) selector //用于动态调用类型或者对象上的一个方法

解释:

      SEL类型,用于表示objc的一个方法

      @selector(方法名)   例如:@selector(initWithWidth:andHeight:)不要丢掉冒号啊

      Class id  SEL 前不需要加星号

@import "MySquare.h" int main(argc,const char * argv[]){ MyRectangle *rec = [[MyRectangle alloc] initWithWidth:2 andHeight:5]; [rec area]; MySquare *squa = [[MySquare alloc] initWithSize:6]; [squa area]; //判断对象是否是clazz的实例,不包含子类的实例 if([squa isMemberOfClass:[MyRectangle class]]){ NSLog(@"squa isMemberOfClass MyRectangle."); }else{ NSLog(@"squa not isMemberOfClass MyRectangle."); } if([squa isKindOfClass:[MySquare class]]){ NSLog(@"squa isKindOfClass MySquare."); }else{ NSLog(@"squa not isKindOfClass MySquare."); } //判断对象是否是clazz的实例或者子类的实例 if([squa isKindOfClass:[MyRectangle class]]){ NSLog(@"squa isKindOfClass MyRectangle."); }else{ NSLog(@"squa not isKindOfClass MyRectangle."); } if([squa isKindOfClass:[MySquare class]]){ NSLog(@"squa isKindOfClass MySquare."); }else{ NSLog(@"squa not isKindOfClass MySquare."); }
//判断对象或类型是否有能力回应指定方法 if([squa respondsToSelector:@selector(initWithSize:)]){ NSLog(@"YES"); }else{ NSLog(@"NO"); } if([MySquare respondsToSelector:@selector(alloc)]){ NSLog(@"YES"); }else{ NSLog(@"NO"); } if([rec respondsToSelector:@selector(initWithWidth:andHeight:)]){ NSLog(@"YES"); }else{ NSLog(@"NO"); } //判断类产生的实例是否有能力回应指定的方法 if([MySquare instanceRespondsToSelector:@selector(initWithSize:)]){ NSLog(@"YES"); }else{ NSLog(@"NO"); } if([MySquare instanceRespondsToSelector:@selector(alloc:)]){ NSLog(@"YES"); }else{ NSLog(@"NO"); } //动态调用类或者对象上的一个方法 id x_id = [rec performSelector:@selector(area)]; [MyRectangle performSelector:@selector(alloc)]; [rec release]; [squa release];
4、类别

想扩充一个类的功能,但有不想使用继承,就可以选择类别

写一个Fraction的类别,为Fraction类增加两个方法

//FractionMath.h===================================== #import "Fraction.h" @interface Fraction(Math1) -(Fraction*)mul:(Fraction*)f;//乘法,就是传入一个Fraction作为参数,与当前Fraction进行计数 -(Fraction*)div:(Fraction*)f;//除法 @end @interface Fraction(Math2) -(Fraction*)add:(Fraction*)f; @end //FractionMath.m ======================================= #import "Fraction.h" @implementation Fraction(Math1) -(Fraction*)mul:(Fraction*)f{ return [[Fraction alloc] initWithNumerator:numerator *[f numerator] denominator:denominator*[f denominator]]; } -(Fraction*)div:(Fraction*)f{ return [[Fraction alloc] initWithNumerator:numerator *[f denominator] denominator:denominator*[f numerator]] } @end @implementation Fraction(Math2) -(Fraction*)add:(Fraction*)f{ return [[Fraction alloc] initWithNumerator: numerator *[f denominator] + denominator*[f numerator] denominator:denominator*[f denominator]]; } @end //main.m====================================== #import "FractionMath.h" int main(int argc,const char *argv[]){ Fraction *frac1 = [[Fraction alloc] initWithNumerator:1 denominator:3]; Fraction *frac2 = [[Fraction alloc] initWithNumerator:2 denominator:5]; Fraction *frac3 = [[frac1 mul:frac2]; [frac1 print]; NSLog(@"*"); [frac2 print]; NSLog(@"="); [frac3 print]; NSLog(@"\n"); Fration *frac5 = [frac1 add:frac2]; [frac2 print]; NSLog(@"+"); [frac2 print]; NSLog(@"="); [frac2 print]; NSLog(@"\n"); [frac1 release]; [frac2 release]; [frac3 release]; [frac5 release]; return 0; }
注意:

类别不可以声明新的实例变量,而且一旦你定义的方法与原始类中的方法名相同,那么原始方法将被隐藏起来

因为不是继承结构,你不能在类别中的方法使用super激活原始类的同名方法

类别还有一个功能,就是隐藏方法,我们在Fraction.m的最后增加如下方法

@interface Fraction(Math3)

-(Fraction*)sub:(Fraction*)f;//减法

@end


@implementation Fraction(Math3)

-(Fraction*)sub:(Fraction*)f{

return [[Fraction alloc] initWithNumerator:

numerator*[f denominator]-denominator*[f numerator]

denominator:denominator*[f denominator]];

}

@end

在。m文件中定义@interface?是的,因为@interface一旦定义在。m文件中,它就不能以header文件形式被导入到其他的类里了,

也就是这样的@interface中定义的方法相当于隐藏了,只有zhege。m编译单元内看见

}

转载于:https://www.cnblogs.com/landebug/archive/2012/02/14/2416671.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值