FROM: http://bbs.itheima.com/thread-247063-1-1.html
动态数据类型id:
Dog * dd = (Dog *)dog;//强制转换为子类类型
[dd kanMen];//只有强制转换后才能调用子类特有的方法
在多态中,通过动态数据类型定义变量,可以调用子类特有的方法;
id dog = [[Dog alloc]init];//创建一条狗;
[dog kanMen];//这条狗可以直接调用Dog类具有的特有方法;
[dog test];//这条狗还可以调用Dog私有的方法//只有实现没有生命的方法是私有方法;
Dog * dd = (Dog *)dog;//强制转换为子类类型
[dd test];//不能调用子类的私有方法
在多态中,如果父类有私有方法,只能在本类的方法中调用,如果子类中有父类私有方法的方法声明,则子类的对象可以直接调用父类的私有方法;(说明,OC中没有真正的私有方法,通过某种途径,父类也是可以调用其私有方法.)
id也存在弊端,由于动态数据类型可以调用任意方法, 所以有可能调用到不属于自己的方法, 而编译时又不会报错, 所以可能导致运行时的错误;
为了避免动态数据类型引发的运行时的错误, 一般情况下如果使用动态数据类型定义一个变量, 在调用这个变量的方法之前会进行一次判断, 判断当前变量是否能够调用这个方法;
//isKindOfClass , 判断指定的对象是否是某一个类, 或者是某一个类的子类
[dog eat];
}
//-------------------------------------------------------------------------------------------------------------
if ([dog isMemberOfClass:[Dog class]]) {
// isMemberOfClass : 判断指定的对象是否是当前指定的类的实例
[dog eat];
}
id的应用场景: 多态, 可以减少代码量, 避免调用子类特有的方法需要强制类型转换
#import <Foundation/Foundation.h>
@interface Animal : NSObject
-(void)eat;
@implementation Animal
-(void)eat
{
NSLog(@"吃饭");
}
-(void)test2
{
NSLog(@"Animal私有方法test2");
}
@end
//———————————————————————//
@interface Dog : Animal
-(void)eat;
-(void)kanMen;
-(void)test2;
@end
@implementation Dog
-(void)eat
{
NSLog(@"dog吃肉");
}
-(void)kanMen
{
NSLog(@"汪汪叫");
}
-(void)test
{
NSLog(@"私有方法test");
}
@end
//——————————————————————//
@interface Person : NSObject
-(void)eat:(Animal*)an;
@end
@implementation Person
-(void)eat:(Animal *)an
{
[an eat];
}
@end
//———————————————————————//
int main(int argc, const char * argv[]) {
// Animal *dog = [[Dog alloc]init];
// [dog eat];
//多态情况下,如果需要调用子类的特有属性,需要强制装换为子类类型
// Animal * dog = [[Dog alloc]init];
// Dog * dd = (Dog *)dog;
// [dd kanMen];
// [dd test];
//使用id类型,在调用子类特有方法的时候,不用再强制转换,可以直接调用;
//使用id类型,可以调用子类的私有方法;
id dog = [[Dog alloc]init];
// [dog kanMen];
// [dog test];
[dog test2];//
// 为了避免动态数据类型引发的运行时的错误, 一般情况下如果使用动态数据类型定义一个变量, 在调用这个变量的方法之前会进行一次判断, 判断当前变量是否能够调用这个方法
// id dog2 = [[Dog alloc]init];
// if ([dog2 isMemberOfClass:[Dog class]] ) {
// [dog2 eat];
// }
//
// Animal * an = [[Animal alloc]init];
// Dog * dog = [[Dog alloc]init];
// Person * p = [[Person alloc]init];
// [p eat:dog];
//真正意义的面向对象;只剩下具体的对象,
//这里是又创建了一个人,和分别创建了一条狗和一只猫,然后就是人去喂猫和狗;
return 0;
}
from: http://blog.csdn.net/batac_lee/article/details/50576314