Objective-C代码学习大纲(3)

2011-05-11 14:06 佚名 otierney 字号:T | T

本文为台湾出版的《Objective-C学习大纲》的翻译文档,系统介绍了Objective-C代码,很多名词为台湾同胞特指词汇,在学习时仔细研读才能体会。

AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载!

详细说明...

多重参数

目前为止我还没展示如何传递多个参数。这个语法乍看之下不是很直觉,不过它却是来自一个十分受欢迎的 Smalltalk 版本。

  1. Fraction.h
  2. ...
  3. -(void) setNumerator: (int) n andDenominator: (int) d;
  4. ...
  5. Fraction.m
  6. ...
  7. -(void) setNumerator: (int) n andDenominator: (int) d {
  8. nnumerator = n;
  9. ddenominator = d;
  10. }
  11. ...
  12. main.m
  13. #import
  14. #import "Fraction.h"
  15. int main( int argc, const char *argv[] ) {
  16. // create a new instance
  17. Fraction *frac = [[Fraction alloc] init];
  18. Fraction *frac2 = [[Fraction alloc] init];
  19. // set the values
  20. [frac setNumerator: 1];
  21. [frac setDenominator: 3];
  22. // combined set
  23. [frac2 setNumerator: 1 andDenominator: 5];
  24. // print it
  25. printf( "The fraction is: " );
  26. [frac print];
  27. printf( "\n" );
  28. // print it
  29. printf( "Fraction 2 is: " );
  30. [frac2 print];
  31. printf( "\n" );
  32. // free memory
  33. [frac release];
  34. [frac2 release];
  35. return 0;
  36. }

output

  1. The fraction is: 1/3
  2. Fraction 2 is: 1/5

这个 method 实际上叫做 setNumerator:andDenominator:

加入其他参数的方法就跟加入第二个时一样,即 method:label1:label2:label3: ,而唿叫的方法是 [obj method: param1 label1: param2 label2: param3 label3: param4]

Labels 是非必要的,所以可以有一个像这样的 method:method:::,简单的省略 label 名称,但以 : 区隔参数。并不建议这样使用。

建构子(Constructors)

  1. Fraction.h
  2. ...
  3. -(Fraction*) initWithNumerator: (int) n denominator: (int) d;
  4. ...
  5. Fraction.m
  6. ...
  7. -(Fraction*) initWithNumerator: (int) n denominator: (int) d {
  8. self = [super init];
  9. if ( self ) {
  10. [self setNumerator: n andDenominator: d];
  11. }
  12. return self;
  13. }
  14. ...
  15. main.m
  16. #import
  17. #import "Fraction.h"
  18. int main( int argc, const char *argv[] ) {
  19. // create a new instance
  20. Fraction *frac = [[Fraction alloc] init];
  21. Fraction *frac2 = [[Fraction alloc] init];
  22. Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
  23. // set the values
  24. [frac setNumerator: 1];
  25. [frac setDenominator: 3];
  26. // combined set
  27. [frac2 setNumerator: 1 andDenominator: 5];
  28. // print it
  29. printf( "The fraction is: " );
  30. [frac print];
  31. printf( "\n" );
  32. printf( "Fraction 2 is: " );
  33. [frac2 print];
  34. printf( "\n" );
  35. printf( "Fraction 3 is: " );
  36. [frac3 print];
  37. printf( "\n" );
  38. // free memory
  39. [frac release];
  40. [frac2 release];
  41. [frac3 release];
  42. return 0;
  43. }

output

  1. The fraction is: 1/3
  2. Fraction 2 is: 1/5
  3. Fraction 3 is: 3/10

@interface 裡的宣告就如同正常的函式。

@implementation 使用了一个新的关键字:super

如同 Java,Objective-C 只有一个 parent class(父类别)。

使用 [super init] 来存取 Super constructor,这个动作需要适当的继承设计。

你将这个动作回传的 instance 指派给另一新个关键字:self。Self 很像 C++ 与 Java 的 this 指标。

if ( self ) 跟 ( self != nil ) 一样,是为了确定 super constructor 成功传回了一个新物件。nil 是 Objective-C 用来表达 C/C++ 中 NULL 的方式,可以引入 NSObject 来取得。

当你初始化变数以后,你用传回 self 的方式来传回自己的位址。

预设的建构子是 -(id) init。

技术上来说,Objective-C 中的建构子就是一个 "init" method,而不像 C++ 与 Java 有特殊的结构。

存取权限

预设的权限是 @protected

Java 实作的方式是在 methods 与变数前面加上 public/private/protected 修饰语,而 Objective-C 的作法则更像 C++ 对于 instance variable(译注:C++ 术语一般称为 data members)的方式。

  1. Access.h
  2. #import
  3. @interface Access: NSObject {
  4. @public
  5. int publicVar;
  6. @private
  7. int privateVar;
  8. int privateVar2;
  9. @protected
  10. int protectedVar;
  11. }
  12. @end
  13. Access.m
  14. #import "Access.h"
  15. @implementation Access
  16. @end
  17. main.m
  18. #import "Access.h"
  19. #import
  20. int main( int argc, const char *argv[] ) {
  21. Access *a = [[Access alloc] init];
  22. // works
  23. a->publicVar = 5;
  24. printf( "public var: %i\n", a->publicVar );
  25. // doesn't compile
  26. //a->privateVar = 10;
  27. //printf( "private var: %i\n", a->privateVar );
  28. [a release];
  29. return 0;
  30. }

output

  1. public var: 5

如同你所看到的,就像 C++ 中 private: [list of vars] public: [list of vars] 的格式,它只是改成了@private, @protected, 等等。

Class level access

  1. ClassA.h
  2. #import
  3. static int count;
  4. @interface ClassA: NSObject
  5. +(int) initCount;
  6. +(void) initialize;
  7. @end
  8. ClassA.m
  9. #import "ClassA.h"
  10. @implementation ClassA
  11. -(id) init {
  12. self = [super init];
  13. count++;
  14. return self;
  15. }
  16. +(int) initCount {
  17. return count;
  18. }
  19. +(void) initialize {
  20. count = 0;
  21. }
  22. @end
  23. main.m
  24. #import "ClassA.h"
  25. #import
  26. int main( int argc, const char *argv[] ) {
  27. ClassA *c1 = [[ClassA alloc] init];
  28. ClassA *c2 = [[ClassA alloc] init];
  29. // print count
  30. printf( "ClassA count: %i\n", [ClassA initCount] );
  31. ClassA *c3 = [[ClassA alloc] init];
  32. // print count again
  33. printf( "ClassA count: %i\n", [ClassA initCount] );
  34. [c1 release];
  35. [c2 release];
  36. [c3 release];
  37. return 0;
  38. }

output

  1. ClassA count: 2
  2. ClassA count: 3

static int count = 0; 这是 class variable 宣告的方式。其实这种变数摆在这裡并不理想,比较好的解法是像 Java 实作 static class variables 的方法。然而,它确实能用。

+(int) initCount; 这是回传 count 值的实际 method。请注意这细微的差别!这裡在 type 前面不用减号 - 而改用加号 +。加号 + 表示这是一个 class level function。(译注:许多文件中,class level functions 被称为 class functions 或 class method)

存取这个变数跟存取一般成员变数没有两样,就像 ClassA 中的 count++ 用法。

+(void) initialize method is 在 Objective-C 开始执行你的程式时被唿叫,而且它也被每个 class 唿叫。这是初始化像我们的 count 这类 class level variables 的好地方。

异常情况(Exceptions)

注意:异常处理只有 Mac OS X 10.3 以上才支援。

  1. CupWarningException.h
  2. #import
  3. @interface CupWarningException: NSException
  4. @end
  5. CupWarningException.m
  6. #import "CupWarningException.h"
  7. @implementation CupWarningException
  8. @end
  9. CupOverflowException.h
  10. #import
  11. @interface CupOverflowException: NSException
  12. @end
  13. CupOverflowException.m
  14. #import "CupOverflowException.h"
  15. @implementation CupOverflowException
  16. @end
  17. Cup.h
  18. #import
  19. @interface Cup: NSObject {
  20. int level;
  21. }
  22. -(int) level;
  23. -(void) setLevel: (int) l;
  24. -(void) fill;
  25. -(void) empty;
  26. -(void) print;
  27. @end
  28. Cup.m
  29. #import "Cup.h"
  30. #import "CupOverflowException.h"
  31. #import "CupWarningException.h"
  32. #import
  33. #import
  34. @implementation Cup
  35. -(id) init {
  36. self = [super init];
  37. if ( self ) {
  38. [self setLevel: 0];
  39. }
  40. return self;
  41. }
  42. -(int) level {
  43. return level;
  44. }
  45. -(void) setLevel: (int) l {
  46. llevel = l;
  47. if ( level > 100 ) {
  48. // throw overflow
  49. NSException *e = [CupOverflowException
  50. exceptionWithName: @"CupOverflowException"
  51. reason: @"The level is above 100"
  52. userInfo: nil];
  53. @throw e;
  54. } else if ( level >= 50 ) {
  55. // throw warning
  56. NSException *e = [CupWarningException
  57. exceptionWithName: @"CupWarningException"
  58. reason: @"The level is above or at 50"
  59. userInfo: nil];
  60. @throw e;
  61. } else if ( level < 0 ) {
  62. // throw exception
  63. NSException *e = [NSException
  64. exceptionWithName: @"CupUnderflowException"
  65. reason: @"The level is below 0"
  66. userInfo: nil];
  67. @throw e;
  68. }
  69. }
  70. -(void) fill {
  71. [self setLevel: level + 10];
  72. }
  73. -(void) empty {
  74. [self setLevel: level - 10];
  75. }
  76. -(void) print {
  77. printf( "Cup level is: %i\n", level );
  78. }
  79. @end
  80. main.m
  81. #import "Cup.h"
  82. #import "CupOverflowException.h"
  83. #import "CupWarningException.h"
  84. #import
  85. #import
  86. #import
  87. #import
  88. int main( int argc, const char *argv[] ) {
  89. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  90. Cup *cup = [[Cup alloc] init];
  91. int i;
  92. // this will work
  93. for ( i = 0; i < 4; i++ ) {
  94. [cup fill];
  95. [cup print];
  96. }
  97. // this will throw exceptions
  98. for ( i = 0; i < 7; i++ ) {
  99. @try {
  100. [cup fill];
  101. } @catch ( CupWarningException *e ) {
  102. printf( "%s: ", [[e name] cString] );
  103. } @catch ( CupOverflowException *e ) {
  104. printf( "%s: ", [[e name] cString] );
  105. } @finally {
  106. [cup print];
  107. }
  108. }
  109. // throw a generic exception
  110. @try {
  111. [cup setLevel: -1];
  112. } @catch ( NSException *e ) {
  113. printf( "%s: %s\n", [[e name] cString], [[e reason] cString] );
  114. }
  115. // free memory
  116. [cup release];
  117. [pool release];
  118. }

output

  1. Cup level is: 10
  2. Cup level is: 20
  3. Cup level is: 30
  4. Cup level is: 40
  5. CupWarningException: Cup level is: 50
  6. CupWarningException: Cup level is: 60
  7. CupWarningException: Cup level is: 70
  8. CupWarningException: Cup level is: 80
  9. CupWarningException: Cup level is: 90
  10. CupWarningException: Cup level is: 100
  11. CupOverflowException: Cup level is: 110
  12. CupUnderflowException: The level is below 0

NSAutoreleasePool 是一个记忆体管理类别。现在先别管它是干嘛的。

Exceptions(异常情况)的丢出不需要扩充(extend)NSException 物件,你可简单的用 id 来代表它: @catch ( id e ) { ... }

还有一个 finally 区块,它的行为就像 Java 的异常处理方式,finally 区块的内容保证会被唿叫。

Cup.m 裡的 @"CupOverflowException" 是一个 NSString 常数物件。在 Objective-C 中,@ 符号通常用来代表这是语言的衍生部分。C 语言形式的字串(C string)就像 C/C++ 一样是 "String constant" 的形式,型别为 char *。

Objective-C代码学习大纲(3)的更多相关文章

  1. Objective-C代码学习大纲(6)

    2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍了Objective-C代码,很多名词为台 ...

  2. Objective-C代码学习大纲(5)

    2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍了Objective-C代码,很多名词为台 ...

  3. Objective-C代码学习大纲(4)

    2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍了Objective-C代码,很多名词为台 ...

  4. Objective-C代码学习大纲(2)

    2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍了Objective-C代码,很多名词为台 ...

  5. Objective-C代码学习大纲(1)

    2011-05-11 14:06 佚名 otierney 字号:T | T 本文为台湾出版的<Objective-C学习大纲>的翻译文档,系统介绍了Objective-C代码,很多名词为台 ...

  6. 大数据Python学习大纲

    最近公司在写一个课程<大数据运维实训课>,分为4个部分,linux实训课.Python开发.hadoop基础知识和项目实战.这门课程主要针对刚从学校毕业的学生去应聘时不会像一个小白菜一样被 ...

  7. JVM学习——学习方法论&学习大纲

    2020年02月06日22:25:51 完成了Springboot系列的学习和Kafka的学习,接下来进入JVM的学习阶段 深入理解JVM 学习方法论 如何去学习一门课程--方法论 多讨论,从别人身上 ...

  8. u-boot代码学习内容

    前言  u-boot代码庞大,不可能全部细读,只能有选择的读部分代码.在读代码之前,根据韦东山教材,关于代码学习内容和深度做以下预先划定. 一.Makefile.mkconfig.config.mk等 ...

  9. Linux 系统从入门到精通的学习大纲;

    以前没有接触过Linux,生产环境需要,有时候遇到问题,百度一下,问题解决了,在遇到问题,在百度,有时候问题是如何解决的,为什么会解决有点丈二的和尚摸不着头脑, 为此,想用一段时间,系统的学习下Lin ...

随机推荐

  1. Provisional headers are shown(一)

    谷歌浏览器调试的时候,这个警告经常出现.但是每次产生的原因可能都是不一样的. 这篇文档记录我遇到的其中一次. 现象:一个并发的错误信息: CAUTION:request is not finished ...

  2. centos 7 搭建git远程仓储 免密登录

    第一步.安装git服务 yum install git 第二步.创建git用户 adduser git 第三步开启公钥验证 vi /etc/ssh/sshd_config 讲文件中的 #PubkeyA ...

  3. 用注册表更改DNS的代码分享

    用注册表更改DNS,1秒切换完毕,快速又方便,不用麻烦的去等待了,支持远程路劲运行 最进我这里DNS老是间歇性掉,很不稳定,广州地区,如果你的DNS经常需要更换,试试这个批处理, 论坛很多人发过了更改 ...

  4. JavaScript判断浏览器类型及版本(新增IE11)

    $(function () { var Sys = {}; var ua = navigator.userAgent.toLowerCase(); var s; (s = ua.match(/rv:( ...

  5. hdoj 1026 Ignatius and the Princess I 最小步数,并且保存路径

    Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  6. swift 函数.和匿名函数

    函数 注意: 没有定义返回类型的函数会返回特殊的值,叫 Void.它其实是一个空的元组(tuple),没有任何元素,可以写成(). 使用元组作为返回参数,返回多个参数 func count(strin ...

  7. libcpmt.lib (xxx.obj) LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' in XXX.obj

    问题描述: 这样的,我写了个NString类,然后用的VS2013的命令行编译的(NMAKE.exe),并用LNK.exe打包成了NString.lib 然后后来我在VS2013里面建了一个proje ...

  8. MultipartEntity 乱码

    MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Ch ...

  9. Eclipse “cannot be resolved to a type” error

    引言:     eclipse新导入的项目经常可以看到"XX cannot be resolved to a type"的报错信息.本文将做以简单总结. 正文:     (1)jd ...

  10. [C++]红色波浪线是什么意思

    相关资料:https://zhidao.baidu.com/question/242005953.html 问题现象:在写C++代码时,写的注释都是红色波浪线. 问题原因:波浪线表示 词语拼写错误 字 ...