• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Objective-C编程语言官网文档(二)-对象,类以及消息

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

声明:本文档仅为个人学习过程中顺手翻译之作,方便开发的同胞借鉴参考。如有觉得译的不好不到位的地方,欢迎指正,将及时做出更正
尽量尊重原文档,因为首次Objective-C,有些地方可能直译了没有注意该语言的专有词,希望指正。如需转载,请注明出处



我的编程环境:

IDE:XCODE4.3.1

OS: MAC OS X 10.7.4

文章来译自:http://developer.apple.com/

Objects, Classes, and Messaging

本章介绍了Objective-C中使用,实现的对象,类以及消息的相关基础知识。除此之外还介绍了一下运行时环境的相关内容。

运行时系统


Objective-C语言在不同状态下会有所不同,比如编译时,连接时到运行时。一旦有可能,它会动态执行一些操作,例如创建对象并决定应当调用哪个方法。因此,语言不仅需要一个编译器,同时还需要一个运行时系统来执行编译了的代码。对于Objective-C语言来说,运行时系统扮演着类似操作系统的角色。通常你并不需要直接与运行时环境进行交互。要理解运行时提供的功能的话,可以参考Objective-C Runtime Programming Guide.


对象
面向对象编程是围绕对象构建的。一个对象相关的数据,用某些操作运算便能影响该数据,Objective-C提供了一种数据类型,用以识别一个对象变量,即便没有指定该对象的类。


对象基础

面向对象编程是围绕对象构建的。一个对象相关的数据,某些操作运算便能影响该数据。在Objective-C中,这些运算被称作对象的方法。受方法影响的数据是它的实例变量。(在别的环境中,它们可能是指实例变量或者成员变量)。本质上来讲,一个对象将数据结构(实例变量)以及一组进程(方法)绑定到了自身的编程单元中。

Objective-C中,一个对象的实例变量是本质体现,通常,你只能通过对象的方法来访问该对象的状态(你可以指定是否子类或者其它的对象能够通过使用域指令直接访问成员变量)。对于其它想要得到有关对象的信息的,应该提供一个方法来提供上述信息。例如,一个矩形应该有方法可以获取它的尺寸以及位置。

要说更多的话,一个对象仅看得到我们为它设计的方法。而不能错误滴执行了为别的对象设计的方法。就像C方法避免它的本地变量一样,将它们对其它程序不可见, 一个对象将隐藏它的实例变量以及它的方法实现。

id


Objective-C中,对象标示符是一种另类的数据类型:id。这种类型一种可以用于所有对象的泛型类型,忽略具体的类,并且可以用于一个类的实例以及类对象自身。

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,即手动保持,释放。用于你完全掌控并决定对象的生命周期。

    详情可以参考 Advanced Memory Management Programming Guide.

  • 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
    在这个Python 例子中, 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...
    }

    Receiver的实例变量

    一个方法可以自动访问获取到的对象的实例变量。你不必把它们当做参数传给方法。例如上面提到过的 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.
     
                           
                        
                        

    鲜花

    握手

    雷人

    路过

    鸡蛋
    该文章已有0人参与评论

    请发表评论

    全部评论

    专题导读
    上一篇:
    Objective-C资源收藏发布时间:2022-07-12
    下一篇:
    objective-c数组发布时间:2022-07-12
    热门推荐
    热门话题
    阅读排行榜

    扫描微信二维码

    查看手机版网站

    随时了解更新最新资讯

    139-2527-9053

    在线客服(服务时间 9:00~18:00)

    在线QQ客服
    地址:深圳市南山区西丽大学城创智工业园
    电邮:jeky_zhao#qq.com
    移动电话:139-2527-9053

    Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap