Objective-C 学习笔记 - part 1 - 对象、类型、消息

这个系列的内容与官方文档 Objective-C 语言介绍的内容一一对应,总共分为以下几个部分:

  1. 对象、类型、消息
  2. 定义一个类
  3. 为对象分配内存并初始化
  4. 协议
  5. 属性申明
  6. 分类与扩展
  7. 相关引用
  8. 快速枚举
  9. 实现静态行为
  10. 选择器
  11. 错误处理
  12. 线程

总体说来 Objective-C 与主流面向对象的语言如C#, java 有许多共通之处,其核心是建立在C上的一套动态运行时系统,它帮助程序实现动态类型推定,垃圾回收等任务。类似于 IronPython 这种用静态语言去做了一个动态的运行时。

以下是第一部分笔记:

一种面向对象的语言
一个对象库
一套开发工具
一个运行时

在实例对象中,变量是私有的,如果需要访问则需要提供一个专用访问方法。

对象的 id 是一种独立的数据类型 id

不论是实例对象还是类本身都可能有一个id

id anObject;

在面向对象的方法返回中,id 替换了 int 成为默认的返回值类型,而在严格的c果中,仍然还使用 int.

nil 的 id 是 0

id, nil 和其它oc 的类型定义在 objc/objc.h 这个文件中。

isa pointer 这个指针指向了一个对象是何种  Class 的实例。

id 只对运行时的对象有效,它的值是“动态”的,因此不能在编译时通过它获取更多的信息。

动态类型体系在 oc 中被称作 "dynamic binding" 动态类型绑定。

运行时在 isa 变量中存储一些数据结构,因此你可以执行一个对象是否实现了一个方法或者获取它的父级类等操作。

类是一种特殊的对象,它可以提供静态方法的实现。

关于内存管理:

oc 提供两种机制来完成内存管理:

1. 引用计数
2. 垃圾回收

关于对象消息:

要让一个对象执行一个 function ,方法是给它传递一个 “消息”, 格式:
[receiver message];

因为方法名通常用来选定一个方法的实现,因此消息中的方法名一般被称为“选择器 selector”

使用举例:
[myRectangle setOriginX: 20.0 y: 50.0];
在这个例子中,选择器就是 setOriginX:y: 注意它包含了冒号,但是并不指定返回值。

在 oc 中,参数名不可省略,顺序不可改变,也不能使用命名参数象python那样。

必选参数用冒号,可选参数用逗号。

可以向 nil 发送 message 而不会报错,这就是为何不使用“方法调用”而使用消息的方式,因为nil 可以选择不接受这个消息,这是不是说就不用担心在一个空对象上调用了方法而引发错误了?

下面这三段比较重要:
If the method returns any pointer type, any integer scalar of size less than or equal to sizeof(void*), a float, a double, a long double, or a long long, then a message sent to nil returns 0.
If the method returns a struct, as defined by the Mac OS X ABI Function Call Guide to be returned in registers, then a message sent to nil returns 0.0 for every field in the struct. Other struct data types will not be filled with zeros.
If the method returns anything other than the aforementioned value types, the return value of a message sent to nil is undefined.

方法天然获得消息接受方的实例变量访问权。

关于多态

因为方法属于对象,因此,消息的结果取决于当前对象对此方法的实现。

关于动态绑定

一个方法调用与消息模式的最大区别在于:在方法调用中,方法与它的调用对象之间的关系是确定的,而消息传递中则不是这样,它需要在运行时决定调用的到底是哪个方法。

当一个对象接受到一个消息时,消息息会扫描这个对象的方法表,找到匹配的方法并调用它,并且传递一个指向接受方袜例变量的指针给它(这个方法)

发送的消息甚至都可以是一个动态的。

动态解析
允许你在运行时实现一个 class 或者实例方法。

"." 运算符:
oc 提供使用“.”运算符来访问 accessor methords:
myInstance.value = 10; 这个时候并不是真正地“访问一个属性”,只是一个语法糖,实际作用类同于 [myInstance setValue:10];

如查需要访问一个对象的 its own instance variable:
self.age = 10;

如何理解一个对象“自己的属性”?
即没有在它的所属 class 里面定议过的属性,因为没有针对这个属性的 accessor method ,所以要使用 self.XXX 的方法来访问。

Graphic *graphic = [[Graphic alloc] init];
如何理解这段代码?
是否相当于在类Graphic 上调用了一个 方法alloc 产生了一个实例,接着调用这个实例的 init 方法,最后将引用存储在一个指针中。

不要使用“.”访问非属性的方法

不要使用“.”访问只读的属性,因此你可能错误地给它赋值而造成一个运行时错误。

关于类
每个类的构造函数相当于一个静态方法,它负责产生这个类的实例,实例的方法是共享的,但是有自己的实例变量。

cocoa 提供超过 250个class, 有些你可以直接使用,有些需要你根据需要编写子类来进行必要的扩展。

编写基础类是一件细致的工具,不建议自己编写基础类,而应该使用 NSObject

Abstract Class  并不强制你实例化它, 但是你不应该那么做。

可以使用静态变量的方式实现单例模式。

initialization 方法提供在类型实例初始化的时候执行,为了保证它只执行一次,需要这样写:
+ (void)initialize
{
  if (self == [ThisClass class]) {
        // Perform initialization here.
        ...
    }
}
这样的话难道说在一个对象上调用一个方法,对象的方法和它的父级类的同名方法都会被依次调用?待确认。

下面这个是成立的:
[object class] != object_getClass(object) != *((Class*)object)


测试对象类型 :
if ([objectA class] == [objectB class]) { //...


posted on 2011-08-13 11:33  沙加  阅读(578)  评论(0编辑  收藏  举报

导航