在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
声明:本文档仅为个人学习过程中顺手翻译之作,方便开发的同胞借鉴参考。如有觉得译的不好不到位的地方,欢迎指正,将及时做出更正
|
id anObject; |
对于Objective-C的面向对象构造, 方法返回值,id替代int作为默认数据类型。(对于严格的C来说,函数返回值,int仍然是默认类型)
关键字nil用于定义一个空对象,一个拥有值,0.id,nil,可以在objc/objc.h中找到其它类型的Objective-C基础类型定义。
下面的例子中id被定义为指向一个数据构造函数的指针。
typedef struct objc_object { |
Class isa; |
} *id; |
每个下面这种类型对象都有一个isa变量,该变量可以告诉我们它是哪个类的实例。因为Class类型自身被定义成了一个指针。
typedef struct objc_class *Class; |
isa
通常被成为“isa
指针.”
动态类型
id类型是完全不严格的。就它自身来说,它没有产生任何有关一个对象的信息,当然除了它是一个对象。从某种意义上来说,一个程序通常需要得到更多有关一个对象它说包含的特定信息。因为id类型标示符无法为编译器提供这种特定信息,这些对象必须在运行时能够提供出这些信息。
isa实例变量知名了对象的类,该对象是什么类型的对象。拥有相同的行为(方法)以及相同的数据(实例变量)的对象是属于相同的类。
这种对象是运行时的动态类型。只要需要,运行时系统随时都可以找到该对象所属的准确的类,只要通过询问该对象。(要想了解关于运行时的信息,可以看考Objective-C Runtime Programming Guide一文)。Objective-C中的动态类型是作为动态绑定的基础进行服务的,晚些时候我们会进一步进行讨论。
isa变量同样可以让对象进行自省操作--以找到关于它们自己的信息(或者其它对象)。编译器会记录供运行时系统使用的有关类在数据结构中的定义相关信息。使用运行时系统时,你可以决定是否一个对象实现了一个特定的方法或者查找它的父类的名字。
我们将在“Classes”一章详细讨论对象类。
它还可以通过静态的在源代码中输入类名来为编译器提供对象类的信息。类是特定类型的对象,并且类名是作为类型名来使用的。可以参考“Class Types”和 “Enabling Static Behavior.”
内存管理
在任何程序中,当对象不在使用时确保它们被正确释放都是极其重要的,否则你的应用的内存轨迹会超出它们实际需要的量。同样重要的是,我们应当确保不要去释放正在使用中的对象。
Objective-C 提供了三种方式来让我们实现上述目标:
Automatic Reference Counting (ARC), 自动引用统计,编译器会推断出所有对象的生命周期
Manual Reference Counting (MRC), 手动引用统计,有时也叫MRR,即手动保持,释放。用于你完全掌控并决定对象的生命周期。
Garbage collection, 垃圾回收,将决定对象生命周期的责任传递给自动回收器
可以参考Garbage Collection Programming Guide. (但文档不适用于iOS—IOS的你可以通过访问IOS开发中心获取该文档.
对象消息
本节主要介绍了发送消息的语法,包括如何嵌套消息异常。我们还将讨论有关一个对象实例变量的可见域方面的问题。以及多态和动态绑定的概念。
要让一个对象去做一些事情,你需要给它他送一个消息,告诉它去请求一个方法。在Objective-C中,消息异常被放在方括号中;
[receiver message] |
receiver是一个对象,并且消息告诉它该驱做什么。在源代码中,小时仅是一个方法的名字以及需要传递给它的参数。当消息发送后,运行时系统会从receiver的指令系统中选择恰当的方法并调用它。
例如,下面这条消息告诉 myRectangle
对象执行它的display
方法, 这个方法会让这个矩形显示它自己;
[myRectangle display]; |
消息后面会有一个分号 “;
” 就像任何C中的语句一样。
因为消息中的方法名用于选择实现方法, 在消息中的方法名通常也被称为选择器( selectors)。
方法可以带参数。单个参数的消息,参数后面会有一个冒号(:
) ,冒号后面是参数的值
[myRectangle setWidth:20.0]; |
对于有多个参数的方法, 形式类似单个参数,多个参数间用空格分开,格式也是 参数名:参数值
[myRectangle setOriginX: 30.0 y: 50.0]; // This is a good example of |
// multiple parameters |
选择器的名字包含名字的所有部分,包括冒号, 如上面看到的例子那样,当然还可以包含任何其它需要的,比如返回值类型以及参数类型
注意 Objective-C 选择器名的字部分不是可选的,它们的顺序也不能改变。在一些其它的语言中, “named parameters” 以及 “keyword parameters” 在运行时可以改变,可以拥有默认值,可以有不同的顺序,并且可能有额外的命名参数。这些特性Objective-C是没有的.
无论怎么说,一个 Objective-C 方法声明只是一个简单的带有两个额外参数的C函数 (可以参考Objective-C Runtime Programming Guide文档中的 “Messaging” 获取更多信息). 因此, Objective-C 方法声明的结构不同于那些使用named 或者 keyword 参数的语言,比如Python, 就像下面的 Python 例子所描述的:
def func(a, b, NeatMode=SuperNeat, Thing=DefaultThing): |
pass |
Thing
和 NeatMode
可能在被调用时被忽略或者有不同的值
在日常操作中, Rectangle
类可以简单的替代实现setOrigin::
方法,而没有第二个参数的任何标签,调用的时候如下面的例子:
[myRectangle setOrigin:30.0 :50.0]; // This is a bad example of multiple parameters |
语法上是合法的,setOrigin::
没有将方法名与参数交叉。因此第二个参数没有任何标签,但这样会让看这段代码的人很困惑,不知道这些参数是做什么的。
一个方法有可变参数也是可能的,尽管这种情况很少出现。额外的参数用逗号分开。在下面的例子中 makeGroup:
方法传递了一个必须的参数 (group
) 一起另外三个可选的参数:
[receiver makeGroup:group, memberOne, memberTwo, memberThree]; |
类似标准的C函数,方法可以有返回值。
BOOL isFilled; |
isFilled = [myRectangle isFilled]; |
我们注意到变量和方法可以拥有一样的名字。
一个消息表达式可以嵌套在另外一个消息的内部。下面的例子是一个矩形的颜色设置给了另外一个矩形的颜色。
[myRectangle setPrimaryColor:[otherRect primaryColor]]; |
Objective-C 同样也提供了逗点(.
)操作符,它可以提供方便的途径来调用一个对象的可访问方法。逗点操作符通常用在与声明的属性连接的特性,具体可以参考(“Declared
Properties”) ,逗点操作符的语法描述可以看 “Dot
Syntax.”
发送消息给nil
Objective-C中,发送消息给nil是有效的—只是在运行时不会产生什么效果。在Cocoa 中可以有几个方面来利用这种特性。从发送到nil的消息返回的值同样也是有效的:
如果方法返回一个对象,那么一条发往nil
的消息将返回0
(nil
).
例如:
Person *motherInLaw = [[aPerson spouse] mother]; |
如果这里的 spouse
对象是 nil
,
那么 mother
会发送到nil
并且方法会返回 nil
.
如果方法返回任何指针类型, 任何整型的表两只大小会小雨或者等于sizeof(void*)
, 一个float
,
double
,long double
, 或者long
long
, 那么一条消息发送到nil
将返回 0
.
如果方法返回一个 struct
, 就像 Mac
OS X ABI Function Call Guide 定义的那样,从寄存器中返回,那么一条消息发往nil
将对于每个struct
中的成员返回 0.0
, 其它 struct
数据类型不会被填充没0
如果方法返回任何前述的值类型,那么发往 nil
消息的返回值将是undefined.
The following code fragment illustrates a valid use of sending a message to nil
.
id anObjectMaybeNil = nil; |
|
// this is valid |
if ([anObjectMaybeNil methodThatReturnsADouble] == 0.0) |
{ |
// implementation continues... |
} |
一个方法可以自动访问获取到的对象的实例变量。你不必把它们当做参数传给方法。例如上面提到过的 primaryColor
方法没有带任何参数,它还是为otherRect
找到了主颜色并将其返回.
每个方法都采用receiver 以及它的实例变量,无需将它们声明为参数。
这个约定简化了Objective-C 代码. 它也支持面向对象编程的程序员所想的对象及消息。消息传给receivers就好像信件邮寄到你的家里。消息从外部携带着参数给 receiver; 它们没必要再将receiver传给它自己.
一个方法只可以自动访问获取到receiver的实例变量。如果它要求其它有关存储在另一个对象的变量信息,那么它必须发送一条消息给哪个对象,向它请求以获取该变量的内容。上面提到的primaryColor
和 isFilled
方法就是处于这个目的使用的。
需要获取更多关于实例变量的信息,可以参考 “Defining a Class”
像上面一些例子描述的,在Objective-C中的消息展现出来的功能就像标准的函数调用。但是,因为方法是 “属于” 一个对象, 消息并不需要像一个传统的函数调用那样行事。
通常,一个对象可以操作我们为其设计好的方法。为其它对象设计的方法不能迷惑它们,即便方法名相同。但是,两个对象可以对同一个消息做出不同的应答。例如,每个对象在接收到 display
消息时都可以以其独有的方式展现自身。
这个特性,被称为多态,在面向对象编程中扮演着很重要的角色。同样重要的还有动态绑定,它使得我们写的代码可以应用到许许多多不同的对象中,无需在你写这些代码时就选择对象的类型是什么。还可能是应用到晚些时候才开发的对象上,被其它程序猿用在别的项目中。如果你写的代码发送了一个 display
消息给 id
变量,任何拥有display
方法的对象都称为潜在的接收者.
当消息发送后,一个运行时消息例程会查看接收器以及消息中的方法名。它会定位匹配接收器的方法实现并“调用”这个方法,给它传递一个指向接收器实例变量的指针。(要了解更多关于这个例程的信息,可以参考 Objective-C Runtime Programming Guide中的 “Messaging”一节)
消息的动态绑定方法与多态特性赋予了面向对象编程强大的可伸缩性。因为每个对象都有它们自己的方法,一条Objective-C 语句可以得到各种结果,并非通过改变消息,而是靠改变接收消息的对象。接收器可以在程序运行时动态决定。接收器可以根据用户的动作等做出决定。
当执行基于Application Kit (AppKit)的代码时,例如,用户决定哪个对象需要从菜单命令中接收消息,如剪切,复制以及粘贴等。消息会找到当前正控制当前选项的对象。一个用来显示文本的对象与一个用来显示扫描图像的对象会对复制这个消息产生不同的反应。因为消息直到运行时才会选择所需的方法(换句话来讲,因为消息绑定的方法只有运行时才会执行), 这些行为上的不同让不同方法区别开来。发送消息的代码不用关注它们。它甚至不必猜测可能性。一个应用的对象都能以其队友的方式对复制这个消息做出回应。
Objective-C 让动态绑定更进的一步,并且甚至允许被发送给变量的消息运行时才决定。至于如何实现,我们将在Objective-C
Runtime Programming Guide中的 “Messaging”一节进行讨论。
动态方法方案
你可以在运行时使用动态方法放来提供类和实例方法的实现。具体可以参考Objective-C
Runtime Programming Guide 的“Dynamic
Method Resolution”一节。
Objective-C 提供了逗点 (.
) 操作符,它可以为我们提供另外一种具有传统的方括号([])的功能的方式来访问方法。用法与C中类似
myInstance.value = 10; |
printf("myInstance value: %d", myInstance.value); |
下面的例子与上例等效
[myInstance setValue:10]; |
printf("myInstance value: %d", [myInstance value]); |
因此,如果你要通过使用访问方法来访问一个对象自己实例变量,你需要显示的调用self例如:
self.age = 10; |
等价于
[self setAge:10]; |
如果在属性传递中产生了一个nil
值,那么结果跟把相同的消息发送给nil是一样的。下列几对语句效果是等效的:
// Each member of the path is an object. |
x = person.address.street.name; |
x = [[[person address] street] name]; |
|
// The path contains a C struct. |
|
请发表评论