文章目录
OC指针类型的变量有两个,一个是编译时的类型,一个是运行时的类型;编译时的类型由声明该变量时使用的类型决定,运行时的类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。
多态性
//FKBase.h
#import <Foundation/Foundation.h>
@interface FKBase : NSObject
- (void) base;
- (void) test;
@end
//FKBase.m
#import<Foundation/Foundation.h>
#import "FKBase.h"
@implementation FKBase
- (void) base
{
NSLog(@"父类的普通base方法");
}
- (void) test
{
NSLog(@"父类的将被覆盖的test方法");
}
@end
//FKSubclass.h
#import <Foundation/Foundation.h>
#import "FKBase.h"
@interface FKSubclass : FKBase
- (void) sub;
@end
//FKSubclass.h
#import "FKSubclass.h"
@implementation FKSubclass
- (void) test
{
NSLog(@"子类的覆盖父类的testd方法");
}
- (void) sub
{
NSLog(@"子类的sub方法");
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "FKSubclass.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
FKSubclass* bc = [[FKBase alloc] init];
[bc base];
[bc test];
FKSubclass* sc = [[FKSubclass alloc] init];
[sc base];
[sc test];
[sc test];
FKBase* ploymophicBc = [[FKSubclass alloc] init];
[ploymophicBc base];
[ploymophicBc test];
//因为ploymophiBc的变异类型是FKBase
//FKBase类没有提供sub方法,所以s下面代码编译时会出现错误;
// [ploymophicBc sub];
//可将任何类型的指针变量赋值给id类型的变量
id dyna = ploymophicBc;
[dyna sub];
}
return 0;
}
效果
1.第三个指针变量ploymophicBc编译时类型是FKBase,而运行时类型是FKSubclass,当调用该指针变量test方法时(FKBasel类中定义了该方法,子类FKSubclass重写了父类的该方法),实际执行FKSubclass类中覆盖后的test方法,这就可能出现多态。
2.因为子类是一种特殊的父类,所以OC允许把一个子类对象直接赋给一个父类指针变量,无须任何类型转换,或者被称为向上转型,向上转型由系统自动完成。
3.当把一个子类对象直接赋值给父类指针变量指针变量,其方法行为总是表现出子类方法分行为特征,而不是父类方法的行为特征,这就可能出现:相同类型的变量调用一个方法时呈现出多种不停的行为特征,这就是多态。
指针变量的强制类型转换
编写OC时,除了id类型,指针变量只能调用它编译时类型的方式,而不能调用它运行时类型的方法,即使它实际所指对象确实包含该方法,如果需要让这个指针变量调用它运行时类型的方法,则必须强制类型转换成运行时的类型,强制类型转换需要借助类型转换运算符。
用法:
(type*)variable
注:1.这种强制类型转换只是改变了该指针变量的编译时类型,但该变量所指向对象的实际类型并不会发生任何改变。
2.当把一个父类对象赋给子类指针变量时,就需要强制类型转换,而且还可能在运行时产生错误。
判断指针变量的实际类型
为了保证程序能正常运行,一般建议在执行强制转换前先判断该对象是否为该类
,或其子类的实例。判断指针变量实际指向的对象是否为某个类、某个子类的实例,可通过以下两个方法完成:
-(BOOL) isKindOfClass:clazz: 判断该对象是否为clazz或其子类的实例
-(BOOL) isSubclassOfClass:clazz: 判断该对象是否为clazz的子类的实例
上面两个方法可使用任何对象作为调用者,接着向该方法传入任意类,该方法将会返回一个BOOL类型的值,用于表明该变量实际指向对象的类型。
示例:
使用isKindOfClass:方法可以非常方便地判断一个指针变量所指对象的实际类型,而isKindOfClass:方法的作用是:在执行强制类型转换之前,首先判断前一个对象是否是该类的实例,是否可以成功地转换,从而使代码更加强壮。