对多态的探究
前言
OC中的指针变量有两个,一种是编译时的类型,一种是运行时的类型
编译时的类型由声明该变量时使用的类型决定
运行时的类型由实际赋给该变量的对象决定
如果编译与运行时的类型不一致就可能出现所谓的多态。
多态性
我们用一个程序来解释多态
首先定义父类子类:
父类实现部分:
子类实现部分:
函数部分:
将子类对象赋给父类指针变量,这里他就出现了多态。
a编译时的类型是FKBaba类型,运行时的类型是FKSon类型。
同时指针变量在编译是只能调用其编译类型所具有的方法,但运行时将执行运行时类型所具有的方法
我们以这个程序为例子,虽然我们定义了父类的指针变量,但是我们指针变量所指向的对象是子类。
所以我们只能调用父类中的方法,但是因为我们的变量实际指向子类,所以我们用的方法实际上是子类中覆盖父类的方法或父类继承给子类的方法。
这也是为什么我们在上方调用子类中单独定义的方法会出错的原因。
当把一个子类对象直接赋给父类指针变量,例如我们上方的初始化操作,a变量编译时是FKBaba类型,运行时类型是FKSon。当运行时调用该指针变量的方法,其方法行为总是表现出子类方法的行为特征。这就可能出现:相同类型的变量调用同一个方法呈现出不同的行为特征,这就是多态
为了解决编译时类型检查的问题我们就要用到id。
任何对象与任何类型的指针变量都可以赋给id类型的变量。
也就是说我们让id类型的指针变量指向实际的对象,这样就不会出现我们编译与运行时类型不一致的情况。
在我们上方的代码id b = a;的意思是让b指向a所指向的对象。然后id自动判断指针变量的类型,这样就避免了多态的情况。
指针类型强制转换
这一点与C语言十分类似。
除了id类型变量之外,指针变量只能调用编译时的类型方法,而不能调用运行时的类型方法所以我们需要将变量类型强制转换为运行时的类型,也就是对象的类。
b2编译时是NSdata类型,所以编译时调用的方法没错,但是到最后执行时我们在其所指向的对象里找不到对应的方法,就会报错,因为它所指向的对象的类型时NSString类型。
判断指针变量的实际类型
如下两个方法的关键是判断指针变量实际指向的对象是否为某个类,某个子类的实例,一定要记得还有子类,例如我们将NSObject传入,他一定会返回true,因为所有类都是NSObject的子类。