使用对象 - Working with Objects_第1页
使用对象 - Working with Objects_第2页
使用对象 - Working with Objects_第3页
使用对象 - Working with Objects_第4页
使用对象 - Working with Objects_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、使对象 - Working with Objects使对象 - Working with Objects在个 Objective-C 应中部分的作是由于消息跨越对象的态系统被送回和送 达产的。这些对象中的部分是由 Cocoa 或者 Cocoa Touch 所提供的类的实例, 部分是你的类的实例。前章描述了来为个类定义接和实现的语法,其中也包括了实现包含为响应消息 需要被执的代码的法的语法。这章解释了如何给个对象发送这样条消 息,并涵盖了 Objective-C 的些动态特征,包括动态类型和决定哪个法应当在运 时被调的能。在个对象能够被使前,它必须结合为它的属性所做的内存分配和内部值的初始化 以

2、被正确地创建。这章描述了如何嵌套法调来分配和初始化个对象来保证它 是被正确配置的。对象发送并且接收消息尽管在 Objective-C 的对象间中有多种不同的法来发送消息,到前为最普遍的 法是使括号的基础语法,像这样:someObject doSomething;左边的引,在这个案例中的 someObject ,是消息的接收者。右边的消息, doSomething ,是访问接收者的法的名称。换句话说,当上这代码被执 的时候, someObject 将被发送消息 doSomething 。前章描述了如何为个类创建个借,像这样:implementation XYZPerson : NSObject-

3、 (voidsayHello;end和怎样为创建那个类的实现,像这样:implementation XYZPerson- (voidsayHello NSLog("Hello, world!"end注解 :这个例使了个 Objective-C 的字符串字量, “Hello, world!” 。字 符串是在 Objective-C 中个允许为它们的创建使的速记字语法的其中之。 规定 “Hello, world!” 概念上等同于 “An Objective-C string object that represents the string Hello, world!.”字量和

4、对象创建将在这章之后的 中被进步地解释。 假设你已经得到了个 XYZPerson 的对象,你可以像这样给它发送 sayHello 的消 息:somePerson sayHello;发送条 Objective-C 的消息概念上常像调个函数。 为消息 “sayHello” 展了实际的程序流程。图 2-1 基本的消息程序流程为了指定条消息的接收者,理解指针在 Objective-C 中怎样被来指向对象是常 重要的。使指针来跟踪对象C 和 Objective-C 使变量来跟踪数值,就像其他编程语样。在标准 C 语中有许多基本的标量变量被定义,包括整数型,浮点数型和字符型,它 们像这样被声明和赋值:in

5、t someInteger = 42;float someFloatingPointNumber = 3.14f;局部变量,是在个法或函数中被声明的变量,像这样:- (voidmyMethod int someInteger = 42;被限定在法中被定义的作域中。在这个例中, someInteger 在 myMethod 中被声明为个局部变量。旦执到 法的闭合括号, someInteger 将不再可存取。当个局部的标量变量(像个 int或者个 float消失,数值也将消失。Objective-C 对象,相之下,则分配得稍许不同。对象通常法调的简单作域 命更长。特别的,个对象经常需要那些被创建来

6、跟踪它的原始变量要存活更久 的时间。因此,个对象的存储空间是动态地被分配和解除分配的。注解 :如果你习惯于使栈和堆,则当对象在堆上被分配时,个局部变量是在栈上 被分配的。这需要你使 C语中的指针(指向存储空间的地址来追踪它们在存储空间中的位 置,像这样:- (voidmyMethod NSString *myString = / get a string from somewhere. .尽管指针变量 myString (星号指它的指针的作域受 myMethod 作域的限 制,它在存储空间中所指的实际的字符串对象在作域外可能会有更长的存时间。 举例来说,它可能已经存在,或者你可能需要在其他的法

7、调中传递对象。你可以给法参数传递对象如果你在发送条消息时需要传递个对象,你为法参数中的个提供个对象指 针。前章描述了声明只有个参数的法的语法:- (voidsomeMethodWithValue:(SomeTypevalue;因此声明个带有字符串对象的法的语法,看起来是像这样的 :- (voidsaySomething:(NSString *greeting;你可以像这样实现 saySomething:的法:- (voidsaySomething:(NSString *greeting NSLog("%", greeting;指针 greeting 表现得像个局部变量并且被

8、限制在 saySomething:的作域 中。尽管它所指的真实的字符串对象先于法调存在,并且将在法完成后继续存 在。注解 :NSLog(使说明符来指替代单元。就像 C 标准函数库中的 printf(函数。记录到控制台的字符串是通过插提供的值(剩余的参数来修改格式字符串 (第个参数的结果。在 Objective-C 中有个额外的可替代的单元, %,来指个对象。在运时, 这个说明符将随着调 descriptionWithLocale:法(如果它存在或者提供 的对象上的 description 法中的个被替换。 description 法由 NSObject 实现来传回类和对象的存储空间,但是许多

9、Cocoa 和 Cocoa Touch 的类 将它重写来提供更多有的消息。在 NSString 的例中, description 法简单 地返回了它所代表的字符串字符。想要获取更多有关 NSLog(和 NSString 类的说明符使的消息,可参见。法可以返回值就像通过法参数传递值,法直接返回值是有可能的。在这章中到现在每个展 出的法都有个返回值类型 void 。这个 C 语的关键词 void 意味着个法不返 回任何东西。规定返回值类型为 int 意味着法返回个标量整形数值:- (intmagicNumber;法的实现使 C 语中的 return 声明来指在法在结束执之后被传回的值, 像这样:-

10、 (intmagicNumber return 42;忽略个法会返回值的事实是完全可以接受的。在这个例中 magicNumber 法 除了返回个值不做其他任何有的事,但是像这样调法没有任何错误:int interestingNumber = someObject magicNumber;你可以相同的法从法中返回对象。举个例, NSString 类,提供了个 uppercaseString 法 :- (NSString *uppercaseString;当个法返回个纯数值时做法相同,尽管你需要使个指针来追踪结果: NSString *testString = "Hello, world

11、!"NSString *revisedString = testString uppercaseString;当这个法调返回时, revisedString 将会指向个代表 Hello,world! 的 NSString 对象。记住当实现个法来返回个对象时,像这样:- (NSString *magicString NSString *stringToReturn = / create an interesting string. return stringToReturn;尽管指针 stringToReturn 出了作域,字符串对象继续存在当它被作为个返回 值被传递时。在这种状况下有

12、很多存储空间管理的考虑:个返回了的对象(在堆中被创建需要 存在够长的时间使它被法的原有调者使,但不是永久存在,这是因为那样会 导致内存泄露。在很程度上,具有动引计数(ARC 特征的 Objectiive-C 编译 程序会为你照顾到这些需要考虑的地的。对象能给他们发送消息论何时你正在写个法的实现,你可以获得个重要的隐藏值 , self 。概念 上, self 是个指向 " 已经接收到这个消息的对象 " 的法。它是个指针,就像上 的值 greeting ,可以被来在现在接收对象上调法。你也许决定通过修改 sayHello 法来使上的 saySomething:法来重构 XYZP

13、erson 的实现,因此将 NSLog(的调移动到不同的法中。这将意味着你能 进步增加法,像 sayGoodbye ,那将每次联系 saySomething:法来解决真 实的问候过程。如果你稍后想将每个问候在户接中的每个本框中展出来, 你只需要修改 saySomething:法不是仔细检查并单独地调整每个问候法。 新的在当前对象上使 self 来调消息的实现将会是这样的:implementation XYZPerson- (voidsayHello self saySomething:"Hello, world!"- (voidsaySomething:(NSString

14、*greeting NSLog("%", greeting;end如果你这种更新过的实现把消息 sayHello 发送给对象 XYZPerson ,实际的程序 流程将会在 中显。图 2-2和通信时的程序流程 对象可以调被它们的超类实现的法在 Objective-C 中对你来说有另外个重要的关键词,叫作 super 。发送条消息给 super 是调个被进步完善继承链的超类所定义的法的途径。 super 最普遍 的法是重写个法的时候。说你想要创建个新类型的 person 类, “shouting person” 类,它每句问候都 写字母展出来。你可以复制整个 XYZPerson

15、 类并修改每个法中的每个字符串 使它们是写的。但是最简单的法是创建个新的继承 XYZPerson 的类,只要 重写 saySomething:法这样它就会以写的形式展现出来,像这样:interface XYZShoutingPerson : XYZPersonendimplementation XYZShoutingPerson- (voidsaySomething:(NSString *greeting NSString *uppercaseGreeting = greeting uppercaseString; NSLog("%", uppercaseGreeting;

16、end这个例声明了个额外的字符串指针, uppercaseGreeting ,并且将发给初始对象 greeting 的消息 uppercaseString message返回的值赋给它。正如你早些 所见到的,这将成为个将原始字符串中的每个字符转换为写新的字符串对象。因为 sayHello 由 XYZPerson 实现, XYZShoutingPerson 是来继承 XYZPerson 的,你也可以在 XYZShoutingPerson 对象上调 sayHello 对象。 当你在 XYZShoutingPerson 对象上调 sayHello 对象时, self saySomething:.的调

17、将使重写过的实现并且将问候显为写,实际的程 序流程图在 中显。图 2-3 对于个覆写法的程序流程新的实现并不是理想的,是因为如果你确实稍后决定修改 saySomething 的 XYZPerson 实现,户接元素来展问候不是通过 NSLog(,你也将需要修 改 XYZShoutingPerson 的实现。个更好的想法将会是改变 saySomething 的 XYZShoutingPerson 版本来调 超类 (XYZPerson实现来处理实际的问候:implementation XYZShoutingPerson- (voidsaySomething:(NSString *greeting N

18、SString *uppercaseGreeting = greeting uppercaseString; super saySomething:uppercaseGreeting;end由于给对象 XYZShoutingPerson 发送消息 sayHello 来的实际的程序流程如 所。图 2-4 和超类通信时的程序流程对象是被动态创建的正如在这章早些时候描述的,给 Objective-C 对象的存储空间的分配是动态的。创建 个对象的第步是确认有够的存储空间,不仅是对被个对象的类所定义的属性 来说,也要满在它的继承链中在每个超类上所定义的属性。根类 NSObject 提供了个类法, all

19、oc ,为你处理这过程:+ (idalloc;注意到这个法的返回值类型为 id 。这在 Objective-C 中是个特殊的关键词,表 “ 些类型的对象 ” 。它是个对象的指针,就像 (NSObject *,但是又是特别的因为 它不使星号。它在这章的稍后, 中会被更仔细地描述。alloc 法有另外个重要的任务,就是通过将存储空间设为零来清空为对象的属性 分配的存储空间。这避免了个寻常的问题,即存储空间含有之前曾存储的垃圾。 但是这不以完全初始化个对象。你需要将对 alloc 的调和对另个 NSObject 的法 init 的调结合起来: - (idinit;init 法被类使以来确认它的属性在

20、创建时有合适的初始值,它将在下章被详 细介绍。注意到 init 也返回 id 。如果个法返回个对象指针,将那个法的调作为接收者嵌套进另个法的 调时有可能的,由此在个声明中结合了多个消息的调。正确分配和初始化个 对象的法是在对 init 的调中嵌套对 init 的调,像这样:NSObject *newObject = NSObject alloc init;这个例设置了 newObject 对象来指向个新被创建的 NSObject 实例。 最内部的调第个被实现,所以 NSObject 类被送到返回个新被分配的 NSObject 实例的 alloc 法。这个返回的对象之后被作为 init 消息的接

21、收者被 使,它返回对象并赋给 newObject 指针,正如在 中显的那样。 图 2-5嵌套 alloc 和 init 消息 注解 :init 返回个由 alloc 创建的不同的对象是有可能的,所以正如展的那 样,嵌套调是最好的尝试。永远不要在没有将任何指针赋给对象的情况下初始化个对象。作为个例,不要 这样做:NSObject *someObject = NSObject alloc;someObject init;如果对 init 的调返回了些其他的对象,你将留下个初始被分配过但从没有初 始化的对象的指针。初始化法可以携带参数些对象需要需要的值来初始化。个 NSNumber 对象,举例来说,

22、必须它需要 代表的数值来创建。NSNumber 类定义了种初始化法,包括:- (idinitWithBool:(BOOLvalue;- (idinitWithFloat:(floatvalue;- (idinitWithInt:(intvalue;- (idinitWithLong:(longvalue;带有参数的初始化法的调和普通的 init 法是样的 个 NSNumber 对 象像这样被分配和初始化:NSNumber *magicNumber = NSNumber alloc initWithInt:42;类法是分配和初始化的个选择正如在前边的章节中所提到的,个类也可以定义法。法提供了传统

23、的 alloc, init过程的不许嵌套两个法的选择。NSNumber 类定义了个类法来匹配它的初始化法,包括:+ (NSNumber *numberWithBool:(BOOLvalue;+ (NSNumber *numberWithFloat:(floatvalue;+ (NSNumber *numberWithInt:(intvalue;+ (NSNumber *numberWithLong:(longvalue;个法像这样被使:NSNumber *magicNumber = NSNumber numberWithInt:42;这实际上和之前使 allocinitWithInt:的例相同

24、。类法通常指直接 调 alloc 和相关的 init 法,它为便使被提供。如果初始化不需要参数那么使 new 来创建个对象创建个类的实例时使类法 new 是有可能的。这个法由 NSObject 提供并且 在你的超类中不需要被覆写。这实际上和调没有参数的 alloc 和 init 是样的 :XYZObject *object = XYZObject new;/ is effectively the same as:XYZObject *object = XYZObject alloc init;字提供了个简洁的对象 创建语法些类允许你使简洁的,字的语法来创建实例。你可以创建个 NSString

25、实例,举例来说,使个特殊的字记号,像这样: NSString *someString = "Hello, World!"这实际上和分配,初始化个 NSString 或者使它的类法中的个相同: NSString *someString = NSString stringWithCString:"Hello, Worl encoding:NSUTF8String NSNumber 类也允许各种各样的字:NSNumber *myBOOL = YES;NSNumber *myFloat = 3.14f;NSNumber *myInt = 42;NSNumber *myLo

26、ng = 42L;此外,这些例中的每个实际上和使相关的初始化法或者个类法相同。你也可以使个框表达式来创建个 NSNumber ,像这样:NSNumber *myInt = (84 / 2;在这种情况中,表达式被数值表,且个 NSNumber 实例伴随着结果被创建。 Objective-C 也持字来创建不可变的 NSArray 和 NSDictionary 对象;这些将 在 Values and Collections中进步讨论。Objective-C 是种动态语正如之前所提到的,你需要使个指针来追踪存储空间中的个对象。因为Objective-C 的动态特征,你为那个指针使什么特定的类型都没有关

27、系 当你给它 发送消息时,正确的法将总是在相关的对象上被调。id 型定义了个通的对象指针。当声明个变量时使 id 是有可能的,但你会失 去关于对象编译时的信息。考虑以下的代码:id someObject = "Hello, World!"someObject removeAllObjects;在这种情况下, someObject 将指向个 NSString 实例,但是编译器不知道任何 事,事实上它是对象的某类型。消息 removeAllObjects 由些 Cocoa 或者 Cocoa Touch 对象(例如 NsMutableArray定义所以编译器不会抱怨,尽管这个代码

28、 因为个 NSString 对象不能响应 removeAllObjects 会在运时会成个 异常。使个静态类型来重写编写代码:NSString *someObject = "Hello, World!"someObject removeAllObjects;意味着编译器将会由于 removeAllObjects 没有在任何它所知道的公共的NSString 接中被声明成个错误。因为对象的类是在运时被决定的,当创建或者使个实例时你论给变量指定什 么类型都没有差别。要使这章早些时候描述的 XYZPerson 和 XYZShoutingPerson 类,你可能要使下的代码:XYZP

29、erson *firstPerson = XYZPerson alloc init;XYZPerson *secondPerson = XYZShoutingPerson alloc init; firstPerson sayHello;secondPerson sayHello;尽管 firstPerson 和 secondPerson 作为 XYZPerson 的对象都是静态类型 的, secondPerson 在运时将会指向个 XYZShoutingPerson 对象。当 sayHello 法在每个对象上被调时,正确的实现将会被使;对于 secondPerson ,这意味着 XYZSho

30、utingPerson 的版本。确定对象相等如果你需要确定个对象是否和另个对象相同,记住你在使指针是重要的。 标准的 C 语等号运算符 = 被来检测两个变量的值是否相同,像这样:if (someInteger = 42 / someInteger has the value 42当处理对象的时候,运算符 = 被来检测两个单独地指针是否指向个相同的对 象:if (firstPerson = secondPerson / firstPerson is the same object as secondPerson 如果你需要检测两个对象是否代表相同的数据,你需要调个像 isEqual :的 法,从

31、 NSObject 可以获得:if (firstPerson isEqual:secondPerson / firstPerson is identical to secondPerson如果你需要较个对象是否另个对象代表了更或更的值,你不能使标准 C 语的较运算符 > 和 <。相反,像 NSNumber , NSString 和 NSDate 这样的基本 类型,提供了个法 compare:if (someDate compare:anotherDate = NSOrderedAscending / someDate is earlier than anotherDate使 nil

32、在你声明它们的时候初始化纯量变量总是个好主意,否则它们的初始值将包含前 个堆栈的垃圾内容:BOOL success = NO;int magicNumber = 42;这对对象指针来说不是必要的,因为编译器将动把变量设为 nil 如果你不规定任何其他的初始值:XYZPerson *somePerson;/ somePerson is automatically set to nilnil 的值对初始化个对象指针来说是最安全的,如果你没有另个值来使的话。 因为在 Objective-C 中发送消息给 nil 是完全可以接受的。如果你确实给 nil 发送了 消息,显然什么都不会发。注解 :如果你期待从发送给 nil 的消息中获得个返回值,返回值将会是对象返回类 型的 nil 型,数字类型的 0, BOOL 类型的 NO 。返回的结构拥有所有初始化为 0 的成 员。如果你需要检查确认个对象不是 nil (个变量指向存储空间中的个对象,你 可以使标准 C 语中的不等运算符:if (somePerson != ni

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论