ObjectiveC基础——多态与id类型

一、概述

定义:不同对象用自己的方式相应相同的名称的方法的能力叫做多态
多态的本质是动态绑定,程序知道执行时才确定对象所属的类型,是父类指向子类的指针。
优点:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。 赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。

二、多态的代码实现

动物类Animal有方法run,狗类Dog继承了Animal类,并重写了run方法,添加了新的方法eat
Animal.h

#import <Foundation/Foundation.h>

@interface Animal : NSObject
-(void) run;
@end

Animal.m

#import "Animal.h"

@implementation Animal
-(void) run{
    NSLog(@"动物在跑...");
}
@end

Dog.h

#import "Animal.h"

@interface Dog : Animal
-(void) run;
-(void) eat;
@end

Dog.m

#import "Dog.h"

@implementation Dog
-(void) run{
    NSLog(@"狗在跑...");
}
-(void) eat{
    NSLog(@"狗在吃东西...");
}
@end

main.m

#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Animal *a = [Dog new];
        [a run];   //输出:狗在跑...

        //[a eat];  //报错(原因是Animal类没有eat方法,必须经过强制类型转换才能通过编译)
        [(Dog *)a eat];   //输出:狗在吃东西...

    }
    return 0;
}

说明:
多态中,当子类调用父类中不存在的方法时(即子类新增加的方法),无法通过编译,在编译过程中报错。需要将值类型转换才能通过编译,并可以成功运行。

错误示例:

#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {        
        Animal *a2 = [Animal new];
        [(Dog *) a2 eat]; //可以通过编译,但是运行时报错。        
    }
    return 0;
}

说明:栈中的a2指针指向的是堆中的Animal的类,其中的_isa指针指向的是Animal类在代码区中存放的代码,这些代码中并没有eat方法。之所以可以通过编译时因为强制类型转换成Dog类型后,“欺骗”了编译器,使得编译器无法察觉错误。

三、通过NSObject实例化对象

所有类都继承自NSObject,可以说NSObject是所有类的基类,可以通过NSObject实例化任何类。

#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {        
        NSObject *b = [Dog new];
        [(Dog *) b eat];   //输出:狗在吃东西...        
    }
    return 0;
}

四、id类型

id是一种通用的对象类型,他可以用来存储任何类的对象。也可以理解为万能指针。

id的定义中已经包含了*号, 指针定义变量时,不需要再加* 号。

ios5之后推出了instancetype类型,与id类型相比:
1.都可以作为方法的返回值类型
2.instancetype可以返回和方法所在类相同类型的对象,id只能返回位置类型的对象。
3.instancetype只能最为返回值,不能作为参数,而id可以。

#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {        
        id obj = [Dog new];
        [obj eat];   //输出:狗在吃东西...        
    }
    return 0;
}

需要注意的是,和NSObject相比,通过id创建的对象不需要强制类型转换就可通过编译。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值