当时学习Object C的时被人鄙视了一顿,说使用.NET的思想来学Object C就是狗屎;不过也挺感谢这位仁兄的,这让我学习的时候更加的谨慎。今天的学习笔记主要记录Object C中的动态类型相关内容。
首先还是和.NET先对比一下,.NET中存在一个关键字var ,这个估计用过.NET的都知道,除非没有接触过3.0以上版本的。在.NET中能够使用var来声明任何类型的局部变量,负责告诉编译器,该变量需要根据初始化表达式来推断变量的类型,而且只能是局部变量.但是这里要注意的时var 并不是一个新的类型,只是一个关键字而已,在定义参数和返回值的时候都不能使用var.
在.net中还有一个类型dynamic,表示变量的类型在运行时决定,也就是在运行此代码的时候才去校验类型是否符合等,如果类型不符则会抛出异常。而var则会在编译的过程就能够发现类型是否准确。
在这里我们要说Object C中的id类型 和 var 以及 dynamic 有什么区别?
一. Object C中的id类型
在Objective-C 中,id 类型是一个独特的数据类型。在概念上可以转换为任何数据类型。换句话说,id 类型的变量可以存放任何数据类型的对象。在内部处理上,这种类型被定义为指向对象的指针,实际上是一个指向这种对象的实例变量的指针。
先看一段代码了解一下id类型的时候:
id stu=[[Student alloc] init]; [stu eat]; id per=[[Person alloc] init]; [per eat];
以上代码分别用创建了两个类Student 和 Person的实例,类型都是使用的id,并且调用了其相应的方法,成功运行。
二. 动态判断
在Object C中如何判断某个类实例是否是某个类的子类,某个类中是否包含某个方法。这个要求似乎和.NET中的反射有点类似,的确在Object-C中同样提供了类似的方法来动态判断。
我们先定义一个父类:
#import <Foundation/Foundation.h> @interface Person : NSObject{ NSString *name; int age; NSString *address; } @property (nonatomic,retain) NSString *name; @property (nonatomic,assign) int age; @property (nonatomic,retain) NSString *address; -(void) eat; -(void) speak; -(void) write; -(Person *) getPerson; -(id) getString; +(void) Info; @end ---------------------------------------------------------------- #import "Person.h" @implementation Person @synthesize name; @synthesize age; @synthesize address; -(void) eat{ NSLog(@"Person.eat()"); } -(void) speak{ NSLog(@"Person.speak()"); } -(void) write{ NSLog(@"Person.write()"); } -(Person *) getPerson{ Person *p=[[Person alloc] init]; p.name=@"li"; p.age=25; p.address=@"上海"; return p; } -(id) getString{ Person *p=[[Person alloc] init]; p.name=@"lin"; p.age=22; p.address=@"北京"; return p; } +(void) Info{ NSLog(@"Person.Info"); } @end
然后定义一个子类,用于继承Person类。
#import "Student.h" #import "Person.h"
@implementation Student:Person @end
Student类继承了Person类,说明Student类拥有了Person类的所有方法和属性
(1) isMemberOfClass 用于判断是否是某个类的实例
bool flag1=[stu isMemberOfClass:[Student class]]; NSLog(@"%d",flag1); bool flag2=[stu isMemberOfClass:[Person class]]; NSLog(@"%d",flag2);
上面的代码 flag1 为yes, 而 flag2 为 no ,说明 stu 是 Student 类的实例,Student为Person的子类,但是不能判断为Person的实例。
(2) isKindOfClass 判断是否为某个类的实例或者某个类子类的实例
bool flag1=[stu isKindOfClass:[Student class]]; NSLog(@"%d",flag1); bool flag2=[stu isKindOfClass:[Person class]]; NSLog(@"%d",flag2);
因为Student是Person的子类,所以上面flag1,flag2 的都为YES
(3) respondsToSelector 用于判断某个类型或者对象是否有能力回应(调用)指定的方法
bool flag3=[per respondsToSelector:@selector(eat)]; NSLog(@"%d",flag3); bool flag4=[stu respondsToSelector:@selector(eat)]; NSLog(@"%d",flag4); bool flag5=[per respondsToSelector:@selector(Info)]; NSLog(@"%d",flag5); bool flag6=[Person respondsToSelector:@selector(Info)]; NSLog(@"%d",flag6);
上面的代码测试输出结果如下:
2014-03-22 20:28:09.778 Object