1、了解Objective-C语言的起源
Objective-C在C语言的基础上添加了面向对象特性。使用“消息结构”(message structure)而非“函数调用”(function calling)。OC由Smalltalk演化而来,后者是消息型语言的鼻祖。
消息与函数调用的关键区别在于:使用消息结构的语言,其运行时所应执行的代码有运行环境来决定;而使用函数调用的语言,则有编译器决定。
Objective-C的重要工作都由“运行期组件”(runtime component)而非编译期来完成。OC面向对象特性所需的全部数据结构和函数都在运行期组件里。
Objective-C是C的“超集”(superset),所以C语言中的所有功能在编写Objective-C代码时依然适用。因此必须同时掌握C与OC这两门语言的核心概念,方能写出高效的OC代码来。其中有为重要的是要理解C语言的内存模型(memory model),这有助于理解OC的内存模型及其“引用计数”(reference counting)机制的工作原理。需明白OC中的指针是用来指示对象的。想要声明一个变量,令其指代某个对象,可用如下语法:
NSString *string = @"Hello world"; 这种语法基本上是照搬C语言的,它声明了一个名为string的变量,其类型是NSString*。也就是说此变量为指向NSString的指针。所有OC语言的对象都必须这样声明,因为对象所占内存总是分配再“堆空间”(heap space)中,而绝不会分配在“栈”(stack)上。
如下两个指针指向同一个内存地址:
NSString *str1 = @"Hello world";
NSString *str2 = str1; 只有一个NSString实例,两个变量指向此实例,两个变量都是NSString*型。及当前”栈帧“(stack frame)里分配了两块内存,每块内存大小都能容下一枚指针(在32位机器上是4字节,64位上是8字节)。这两块内存里的值都一样,就是NSString实例的内存地址。
分配在堆中的内存必须直接管理,而分配在栈上用于保存变量的内存则会在其栈帧弹出时自动清理。OC将堆内存管理抽象出来,不需要用malloc及free来分配或释放对象所占内存。OC运行期环境把这部分工作抽象为一套内存管理架构:“引用计数”。
在OC代码中,有时候会遇到定义里不含*的变量,它们可能会使用“栈空间”(stack space)。这些变量所保存的不是OC对象。如:CoreGraphics框架中的CGRect:
CGRect frame;
// CGRect是C结构体,定义如下:
struct CGRect {
CGPoint origin;
CGSize size;
};
typedef struct CGRect CGRect; 整个系统框架都在使用这种结构体,因为改用OC对象来做的话,性能会受影响。与创建结构体相比,创建对象还需要额外开销(如:分配及释放堆内存等)。如果只需保存int、float、double、char等“非对象类型”(nonobject type),那么通常使用CGRect这种结构体就可以了。
要点:
OC为C语言添加了面向对象特性,是其超集。OC使用动态绑定的消息结构。及在运行时才会检查对象来袭,接收一消息后,究竟应执行何种代码,由运行期环境而非编译期决定
理解C语言的核心概念有助于写好OC程序,尤其要整我内存模型与指针
Last updated
Was this helpful?