0x01 面向对象编程和过程式编程的区别
过程式编程建立在函数的基础上,数据为函数服务;
面向对象编程则以程序的数据为中心,函数为数据服务。
在OOP中,我们不再重点关注程序中的函数,而是专注于数据。数据通过间接的方式引用代码,代码可以对数据进行操作。
0x02 面向对象编程的对象
对象是什么?
其实这里的对象仍然类似于C语言中的struct,但它能够通过函数指针查找与之相关的代码。接上一小节的程序样例,4种Shape对象:正方形、矩形、圆形和椭圆形,他们都有自己的draw()函数实现绘制自身的功能。
下面,通过Objective-C的面向对象特性,我们来实现drawShapes()函数:
void drawShapes (id shapes[], int count)
{
for (int i = 0; i < count; i++) {
id shape = shapes[i]; //id是一种泛型,可以引用任何类型的对象
[shape draw]; //Objective-C中的发送消息,或者称为调用方法
}
}
id是什么?
id表示标识符(identifier),是一种泛型,可以用来引用任何类型的对象。在这里,id实际上是一个指向结构体的指针。
代码从shape数组中获取指向某个对象的指针,并将其赋给id类型的shape变量。这是一个指针赋值的过程,实质上并不复制shape数组中的内容。
shape数组中的内容如下图所示:
这里的方括号意义不同
在Objective-C中,方括号还有另外一个意义,用于通知某个对象去做什么。在方括号中,第一项是对象,其余项是需要对象执行的操作。在这里,我们通知了shape对象去执行draw操作。
0x03 发送消息后的代码调用
向对象发送消息后,调用代码的幕后需要类对象来协助完成。
类是一种能够实例化成对象的结构体。
虽然直接让每个对象指向各自的代码显得更简单,但使用类对象还是有必要的。因为如果在运行程序的时候改变某个类,则该类的所有对象会自动继承该变化。
图中所示的步骤:
1、查询消息的目标对象(示例中是矩形)属于哪个类;
2、查找对应类的对应的代码块,获取draw函数的地址;
3、执行draw函数的代码。
使用了OOP,我们可以由Objective-C在幕后决定查询对象属于哪个类,这可以降低人为失误的几率,同时代码也更加容易维护。