Objective-C-2.0程序设计-第7章-类.ppt_第1页
Objective-C-2.0程序设计-第7章-类.ppt_第2页
Objective-C-2.0程序设计-第7章-类.ppt_第3页
Objective-C-2.0程序设计-第7章-类.ppt_第4页
Objective-C-2.0程序设计-第7章-类.ppt_第5页
免费预览已结束,剩余39页可下载查看

下载本文档

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

文档简介

第7章类 第7章类 3 7 1分离接口和实现文件 现在 是时候将类的声明和定义放在单独的文件中了 如果正使用Xcode 可新建一个称为FractionTest的项目 在文件FractionTest m中键入以下程序 代码清单7 1主测试程序 FractionTest m import Fraction h intmain intargc char argv autoreleasepool Fraction myFraction Fractionalloc init setfractionto1 3 myFractionsetNumerator 1 myFractionsetDenominator 3 displaythefractionNSLog ThevalueofmyFractionis myFractionprint return0 7 1分离接口和实现文件 注意 该文件未包含Fraction类的定义 然而 它确实导入了一个称为Fraction h的文件 通常 类的声明 interface部分 要放在它自己的名为class h的文件中 而类的定义 implementation部分 通常放在相同名称的文件中 但扩展名为 m 所以把Fraction类的声明放到Fraction h文件中 把Fraction类的定义放到Fraction m文件中 要在Xcode中完成该工作 在File菜单中选择NewFile 在左侧窗口中选择Cocoa 7 1分离接口和实现文件 点击Next 键入Fraction m作为文件名 选中AlsoCreateFraction h框 该文件所在位置应该与FractionTest m文件的文件夹相同 7 1分离接口和实现文件 点击Finish Xcode在项目中添加了两个文件 Fraction h和Fraction m 在此我们不使用Cocoa 所以将Fraction h中的 import改为 import 7 1分离接口和实现文件 代码清单7 1接口文件Fraction h Fraction h FractionTest CreatedbySteveKochanon7 5 08 Copyright2008 MyCompanyName Allrightsreserved import TheFractionclass interfaceFraction NSObject intnumerator intdenominator void print void setNumerator int n void setDenominator int d int numerator int denominator double convertToNum end 7 1分离接口和实现文件 代码清单7 1实现文件Fraction m Fraction m FractionTest CreatedbySteveKochanon7 5 08 Copyright2008 MyCompanyName Allrightsreserved import Fraction h implementationFraction void print NSLog i i numerator denominator void setNumerator int n numerator n void setDenominator int d denominator d 7 1分离接口和实现文件 int numerator returnnumerator int denominator returndenominator double convertToNum if denominator 0 return double numerator denominator elsereturnNAN end 7 1分离接口和实现文件 注意 使用以下语句将接口文件导入到实现文件中 import Fraction h 这样做的目的是 是编译器知道为Fraction类声明的类和方法 同时还能确保这两个文件的一致性 还要提醒一下 一般不能在实现部分重复声明类的实例变量 所以编译器需要从Fraction h中包含的接口部分获取信息需要注意的另一件事是 导入的文件要用一对引号括起来 而不是尖括号字符 双引号用于本地文件 指自己创建的文件 本地文件与系统文件相对 并且它们告诉编译器在哪里找到指定的文件 使用双引号 编译器一般会首先在当前目录寻找指定文件 然后再转到其他位置查找 还要注意 测试程序FractionTest m包括接口文件Fraction h 而不包括实现文件Fraction m 现在 该程序分成了三个独立的文件 对于小程序例子而言 这似乎要花费很多工作 但是 着手处理较大的程序并和其他程序员共享类的声明时 这种实用性就会变得十分明显 编译运行该文件 输出为 ThevalueofmyFractionis 1 3 第7章类 7 2合成存取器方法 从Objective C2 0开始 可自动生成设置函数方法和获取函数方法 统称为存取器方法 我们到目前位置都没有介绍如何实现 原因是知道如何自己编写这些方法非常重要 第一步是在接口部分中使用 property指令标志属性 这些属性通常是实例变量 在Fraction类中 两个实例变量numerator和denominator都属于此类属性 下面是新的接口部分 其中添加了新的 property指令 interfaceFraction NSObject intnumerator intdenominator propertyintnumerator denominator void print double convertToNum end 7 2合成存取器方法 注意 我们没有包括下列设置函数方法和获取函数方法的定义 numerator denominator setNumerator 和setDenominator 我们要让Objective C2 0编译器为我们自动生成这些方法 只需在实现部分中使用 synthesize指令即可 import Fraction h implementationFraction synthesizenumerator denominator void print NSLog i i numerator denominator double convertToNum if denominator 0 return double numerator denominator elsereturnNAN end 7 2合成存取器方法 下面这还内容告诉Objective C编译器 为两个实例变量的每个生成一对设置函数方法和获取函数方法 synthesizenumerator denominator 通常如果有成为X的实例变量 那么在实现部分包括以下会导致编译器自动实现一个获取函数方法X和一个设置函数方法setX synthesizex 第7章类 7 3使用点运算符访问属性 Objective C语言允许你使用非常简便的语法访问属性 要获得myFraction中存储的numerator的值 可使用一下语句 myFractionnumerator 这会向myFraction对象发送numerator消息 从而返回所需的值 从Objective C2 0开始 可以使用点运算符编写以下等价的表达式 myFraction numerator一般格式为 instance property还可以使用类似的语法进行赋值instance property value这等价于编写一下表达式 instancesetProperty value 第7章类 7 4具有多个参数的方法 如果有一个方法能够只用一条消息既可设置numerator同时又可设置denominator就太好了 通过列出每个连续的参数并用冒号将其连起来 就可以定义一个接受多参数的方法 用冒号链接的参数将成为这个方法名的一部分 例如 方法名addEntryWithName andEmail 表示接受两个参数的方法 这两个参数可能是姓名和电子邮件地址 方法addEntryWithName andEmail andPhone 是接收以下3个参数的方法 一个姓名 一个电子邮件和一个电话号码 同时设置numerator和denominator的方法可以命名为setNumerator andDenominator 你可以采取以下形式 myFractionsetNumerator 1andDenominator 3 这种命名方法是首选方式 但是必须为方法指定更易阅读的名称 例如setTo over 通过将myFraction设置为1 3 比较这个名称和前面的名称 myFractionsetTo 1over 3 7 4具有多个参数的方法 代码请7 2接口文件 Fraction h import DefinetheFractionclass interfaceFraction NSObject intnumerator intdenominator propertyintnumerator denominator void print void setTo int nover int d double convertToNum end 7 4具有多个参数的方法 代码清单7 2实现文件 Fraction m import Fraction h implementationFraction synthesizenumerator denominator void print NSLog i i numerator denominator double convertToNum if denominator 0 return double numerator denominator elsereturn1 0 void setTo int nover int d numerator n denominator d end 新的setTo over 方法仅接收两个整型参数 n和d 并把它们赋值给该分数对应的域 7 4具有多个参数的方法 代码请7 2测试文件 mian m import Fraction h intmain intargc char argv autoreleasepool Fraction aFraction Fractionalloc init aFractionsetTo 100over 200 aFractionprint aFractionsetTo 1over 3 aFractionprint return0 输出 100 3001 3 7 4 1不带参数名的方法 创建方法名时 参数名实际上是可选的 例如 可以如下声明一个方法 int set int n int d 注意 和先前的例子不同 这个方法的第二个参数没有名字 这个方法名为set 两个冒号表示这个方法有两个参数 虽然没有全部命名 要调用set 方法 可以使用冒号作为参数分隔符 aFractionset 1 3 在编写新方法时 省略参数名不是一种好的编程风格 因为它使程序很难读懂并且很不直观 特别是当使用的方法参数特别重要时更是如此 7 4 2关于分数的操作 继续讨论上面提到的Fraction类 首先 编写一个方法 将一个分数与另一个分数相加 将一个方法命名为add 并且把一个分数作为参数 这个新方法的声明如下 void add Fraction f 注意参数f的声明 Fraction f这条语句说明add 方法的参数类型是Fraction类 星号是必须的 所以声明 Fraction f是不正确的 你将把一个分数作为参数传递给add 方法 所以表达式 aFractionadd bFraction 将FractionbFraction和FractionaFraction相加 addaFractiontothereceiver void add Fraction f Toaddtwofractions a b c d a d b c b d numerator numerator f denominator denominator f numerator denominator denominator f denominator 7 4 2关于分数的操作 假设将新add 方法的声明和定义添加到接口和实现文件中 代码清单7 3测试文件 FractionTest m import Fraction h intmain intargc char argv autoreleasepool Fraction aFraction Fractionalloc init Fraction bFraction Fractionalloc init Settwofractionsto1 4and1 2andaddthemtogether aFractionsetTo 1over 4 bFractionsetTo 1over 2 Printtheresults aFractionprint NSLog bFractionprint NSLog aFractionadd bFraction aFractionprint return0 输出 1 4 1 2 6 8 第7章类 7 5局部变量 你也许注意到1 4和1 2相加的结果显示为6 8 而不是期望的3 4 所以继续练习如何编写有关分数运算的新方法 编写一个新的reduce方法 将分数相约到它的最简形式 void reduce intu numerator intv denominator inttemp while v 0 temp u v u v v temp numerator u denominator u 7 5局部变量 这个reduce方法中有一些新东西 它声明了三个整型变量u v和temp 这些变量是局部变量 意思是它们的值只在reduce方法运行时才存在并且只能在定义它们的方法中访问 从这个意义上来说 它们类似于在main例程中定义的变量 这些变量对main来说是局部变量 可以在main例程中直接进行访问 其他的方法都不能访问main中的局部变量 局部变量没有默认的初始值 所以在使用前要先赋值 reduce程序中有三个局部变量在使用之前被赋值 和实例变量不同 这些局部变量不存在于内存中 也就是 当方法返回时 这些变量的值都消失了 每次调用方法 该方法中的局部变量都是用变量声明初始化一次 7 5 1方法的参数 方法的参数名也是局部变量 执行方法时 通过方法传递的任何参数都被复制到局部变量中 因为方法使用参数的副本 所以不能改变通过方法传递的原值 假设有个名为calculate的方法 void calculate double x x 2 假设使用一下消息表达式来调用它 myDatacalculate ptVal 执行calculate方法时 ptVal变量所含的任何值都被复制到局部变量x 所以改变calculate中x的值 对ptVal的值没有影响 只影响x变量的数据副本 如果参数是对象 可以更改其中的实例变量的值 7 5 2static关键字 在变量声明前加上关键字static 可以使局部变量保留多次调用一个方法所得的值 例如 staticinthitCount 0 声明证实hitCount是一个静态变量 和其他常见局部变量不同 静态变量的初始值是0 所以前面显示的初始化是多余的 此外 它们只在程序开始执行时初始化一次 并且在多次调用方法时保存这些数值 void showPage staticintpageCount 0 pageCount 静态变量用于记录该方法的调用次数 只在程序开始时局部静态变量设置为0 并且在连续调用showPage方法时获得新值 7 5 2static关键字 注意 将pageCount设置为局部静态变量和实例变量之间的区别 对于前一种情况 pageCount能记录调用showPage方法的所有对象打印页码的数目 对后一种情况 pageCount变量可以计算每个对象打印的页码数目 因为每个对象都有自己的pageCount副本 记住只能在定义静态和局部变量的方法中访问这些变量 所以即使静态变量pageCount 也只能在showPage函数中访问 可以将变量的声明移到所有方法声明的外部 这样所有的方法都可以访问它们 如 import Printer h staticintpageCount implementationPrinter end返回关于分数的讨论 将reduce方法的代码结合到实现文件Fraction m中 不要忘了在接口文件Fraction h中声明reduce方法 7 5 2static关键字 代码清单7 4测试文件FractionTest m import Fraction h intmain intargc char argv autoreleasepool Fraction aFraction Fractionalloc init Fraction bFraction Fractionalloc init aFractionsetTo 1over 4 set1stfractionto1 4 bFractionsetTo 1over 2 set2ndfractionto1 2 aFractionprint NSLog bFractionprint NSLog aFractionadd bFraction reducetheresultoftheadditionandprinttheresult aFractionreduce aFractionprint return0 输出 1 4 1 2 3 4 第7章类 7 6self关键字 在代码清单7 4中 我们决定在add 方法之外约简分数 还可以在add 中进行约简 然而 如何确定使用reduce方法约简的分数 我们知道如何通过变量名直接确定方法中的实力变量 但是不知道如何直接确定消息的接受者 关键字self用来指明对象是当前方法的接受者 如果在add 方法中编写 selfreduce 就可以对Fraction应用reduce方法 它正是你希望的add 方法接受者 现在在add 方法中使用它 下面是修改后的结果 void add Fraction f Toaddtwofractions a b c d a d b c b d numerator numerator fdenominator denominator fnumerator denominator denominator fdenominator selfreduce 第7章类 7 7在方法中分配和返回对象 我们注意到add 方法改变了接受该消息的对象值 创建新版本的add 函数 这个方法创建了一个新的分数来存储相加的结果 在这种情况下 需要向消息的发送者返回新的Fraction 下面是add 的定义 Fraction add Fraction f Toaddtwofractions a b c d a d b c b d resultwillstoretheresultoftheadditionFraction result Fractionalloc init intresultNum resultDenom resultNum numerator f denominator denominator f numerator resultDenom denominator f denominator resultsetTo resultNumover resultDenom resultreduce returnresult 7 7在方法中分配和返回对象 方法的第一行是 Fraction add Fraction f 这一行说明add 方法将返回一个名为Fraction对象 并且说明它还是用一个Fraction作为参数 这个参数将与消息的接受者相加 消息的接受者同样是Fraction 和以前一样执行完加法运算后 将产生的分子和分母赋值给局部变量 然后使用一下消息表达式设置result的值 resultsetTo resultNumover resultDenom 注意在add 方法中分配给Fractionresult的空间被返回 并且没有被系统释放 不能从add 方法中释放 因为add 方法的调用者需要它 因此这个方法的使用者知道返回的对象是一个新变量 并将被随后释放 代码清单7 5测试了新方法add 7 7在方法中分配和返回对象 代码清单7 5测试文件main m import Fraction h intmain intargc char argv autoreleasepool Fraction aFraction Fractionalloc init Fraction bFraction Fractionalloc init Fraction resultFraction aFractionsetTo 1over 4 set1stfractionto1 4 bFractionsetTo 1over 2 set2ndfractionto1 2 aFractionprint NSLog bFractionprint NSLog 7 7在方法中分配和返回对象 resultFaction aFractionadd bFraction resultFractionprint Thistimegivetheresultdirectlytoprint memoryleakagehere aFractionadd bFraction print return0 输出 1 4 1 2 3 43 4 7 7在方法中分配和返回对象 一下代码 resultFraction aFractionadd bFraction resultFractionprint 首先发送add 消息到aFraction对象 同时将bFraction作为它的参数 该方法返回的结果存储到resultFraction中 然后通过向它发送一个print消息 显示结果 注意虽然你没有在main例程中为resultFraction分配空间 但是在程序的末尾一定要将resultFraction释放 它是由add 方法分配空间的 但是由程序员负责清除 消息表达式 aFractionadd bFraction print 看起来很不错 但是它实际上存在一个问题 因为你使用add 方法返回的Fraction类的对象 你没有办法释放add 方法创建的Fraction类对象 这是一个内存泄露的例子 如果程序中有很多这样的嵌套消息 最终这些分数的存储空间就会累加 问题的一个解决方案是将print方法返回给它的接受者 然后可以将它释放 但这有点兜圈子 一个更好的解决方案是将嵌套的消息分成两个单独的消息 和在程序中以前做的一样 7 7在方法中

温馨提示

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

评论

0/150

提交评论