【iOS】——多态(三大特征之一)

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:方法的作用是:在执行强制类型转换之前,首先判断前一个对象是否是该类的实例,是否可以成功地转换,从而使代码更加强壮。

Guess you like

Origin blog.csdn.net/weixin_50990189/article/details/117400829