现在的位置: 首页 > 综合 > 正文

Objective-C 初学者指南

2014年03月06日 ⁄ 综合 ⁄ 共 27062字 ⁄ 字号 评论关闭
转载请标明出处:http://blog.csdn.net/zhangxingping

 

Translations: English |
Chinese
| Korean

Outline

目录

 

·        Getting Started

·        开始

o   Downloading this tutorial

o   下载该教程

      • All the source code for this beginners guide including makefiles is available by downloadingobjc.tar.gz. Many of the examples in this tutorial were written by Steve Kochan in the bookProgramming
        in Objective-C
        . If you want more detailed information and examples, feel free to check out his book. The examples on this site were used with his permission, so please don't copy them.
      • 该初学者教程中的所有源码,包括makefile文件都可以在这里进行下载:objc.tar.gz。本教程中的很多示例程序都是源自于Steve Kochan编写的Programming
        in Objective-C
        。如果你想获取更多详细的信息以及更多的示例程序,可以参见该书中的内容。本网站中使用的示例程序都是经过Steve Kochan本人允许的,所以请不要随便拷贝这些程序。

o   Setting up the environment

o   搭建环境

      • Linux/FreeBSD: Install GNUStep
      • Linux/FreeBSD系统:安装GNUStep
        1. In order to build GNUstep applications one must first execute the GNUstep.sh file in /usr/GNUstep/System/Makefiles/GNUstep.sh. This path depends on your system. Some put it in /usr, some /usr/lib, some /usr/local. If your shell is a csh/tcsh based shell,
          you'll want to execute GNUStep.csh instead. It's recommended that you put this script in your .bashrc or .cshrc.
        2. 我们必须先执行/usr/GNUstep/System/Makefiles/GNUstep.sh这个文件,以便能够构建GNUstep应用程序。该文件的路径取决于您所使用的系统。一些系统将上面的路径放置在/usr/lib目录下,一些则放置在/usr/local目录下。如果你系统中的shell是从C语言衍生而来的,那么您需要执行的是GUNStep.csh。我们建议您将这个脚本文件放置在.bashrc或者.cshrc目录下。
      • Mac OS X: Install XCode
      • Mac OS X系统: 安装XCode
      • Windows NT 5.X: Install cygwin or
        mingw
        and then install GNUStep
      • Windows NT 5.X系统:安装cygwin 或者
        mingw
        然后再安装 GNUStep

o   Preamble

o   序

      • This tutorial assumes you have some basic C knowledge, including C data types, what a function is, what a return value is, knowledge of pointers and basic memory management in C. If you haven't gotten this far, I highly suggest you pick up K and R's book,The
        C Programming Language
        . This is the book on C written by the writers of C.
      • 我们假设您已经有一定的C语言基础,包括C语言中的数据类型,什么是函数,什么是返回值以及指针和基本的内存管理的知识。如果您还不完全具备这些知识,我们强烈建议您先阅读由Brain Kernighan和Dennis Ritchie编写的《The
        C Programming Language
        》(C语言)这本书。其中Dennis Ritchie是C语言的发明者。
      • Objective-C, being a C derivative, inherits all of C's features. There are a few exceptions but they don't really deviate from what C offers as a language.
      • Objective-C是从C语言发展而来的。它继承了C的全部特性,并增加了少量特性。但是增加的这些特性并不影响从C语言继承的东西。
      • nil: In C/C++ you're probably used to NULL. In Objective-C it is nil. The difference is you can pass messages to nil (such as [nil message];) and this is perfectly legal. You cannot however do this with NULL.
      • nil(空):在C/C++中我们使用NULL来表示空。在Objective-C中,我们使用nil。其区别就是我们可以给空(nil)发送消息(例如,[nil message])并且这是完全合法的。然而对于NULL,我们是不能这样做的。
      • BOOL: C doesn't have an official boolean type, and in reality neither does Objective-C. It's however built into the Foundation classes (Namely from importing NSObject.h). nil is also included in this header file. BOOL in Objective-C has two modes, YES and
        NO rather than TRUE and FALSE.
      • 布尔:C语言中没有官方定义的布尔类型,实际上Objective-C中也是没有布尔类型的。然而,布尔类型被构建在了基础框架类中,也就是从NSObject.h中引入的。nil也是被包含在该头文件中的。Objective-C中的布尔类型的取值是YES或者NO,而不是TRUE或者FALSE。
      • #import vs #include: As you will notice in the hello world example, #import was used. #import is supported by the gcc compiler, however it is deprecated in favor of #include. #import is basically the same thing as #ifndef #define #endif at the top and bottom
        of every .h file you make. I find this to be retarded, as many other programmers will most likely agree. For all purposes, just use #import. It's less hassle, and if gcc ever does remove it chances are enough Objective-C developers exist to either keep it
        from getting removed or getting added back in. As an aside, Apple officially uses #import in all their code so if this ever did happen, you can be certain that Apple would conviently ship a forked version of gcc to add this back in.
      • 使用#import还是#include来进行引入呢?后续我们会发现,在hello world示例程序中我们使用#import进行引入。gcc编译器是支持#import的。然而,使用#import进行引入已经不再被提倡了,人们更喜欢使用#include。#import实际上和我们在每个.h头文件的头部和尾部使用的#ifdef #define #endif是相同的。我个人感觉这点看起来很弱智,很多程序员可能都会同意这点。在实际中,我们都使用#import来进行引入,关于这点争议较少。即使gcc确实不打算支持#import了,众多的Objective-C开发人员也会阻止这样事情的发生或者把对#import的支持增加进去。此外,苹果公司官方地在自己的代码中也是用#import来进行引入,因此,如果gcc果真不支持#import了,我们也可以确定苹果公司会提供支持使用#import进行引入的gcc的分支版本。
      • The word method and message are used interchangably in Objective-C, although messages have special properties. A message can be dynamically forwarded to another object. Calling a message on an object in Objective-C doesn't mean that the object implements
        that message, just that it knows how to respond to it somehow via directly implementing it or forwarding the message to an object that does know how to.
      • 在Objective-C中,我们会经常交替使用方法和消息这两个词汇,尽管消息和方法相比有一些特殊性。消息是可以被动态地传递给另外的对象。而调用一个对象的方法在Objective-C中并不意味着该对象就实现了对应的消息,只要该对象能知道该如何响应该消息即可。也许这种响应是通过直接实现具体操作来完成,也许只是简单地把消息转发给能处理该消息的别的对象。

o   Making hello world

o   编写hello world程序

      • hello.m
      • hello.m源文件

§  #import <stdio.h>

§   

§  int main( int argc, const char *argv[] ) {

§      printf( "hello world\n" );

§      return 0;

§  }

      • output
      • 程序输出

hello world

      • You use #import instead of #include in Objective-C
      • 在Objective-C中,我们使用#import而不是#include来进行引入
      • The default file extention for Objective-C is .m
      • Objective-C程序文件的缺省扩展为.m

·        Creating classes

·        创建类

o   @interface

o   定义类使用关键字interface,interface直译为接口

      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)这本书中的示例程序,经授权使用。
      • Fraction.h
      • 声明Fraction类的头文件

§  #import <Foundation/NSObject.h>

§   

§  @interface Fraction: NSObject {

§      int numerator;

§      int denominator;

§  }

§   

§  -(void) print;

§  -(void) setNumerator: (int) n;

§  -(void) setDenominator: (int) d;

§  -(int) numerator;

§  -(int) denominator;

§  @end

      • NSObject: Short for NeXTStep Object. Although this is less meaningful today since it's really OpenStep.
      • NSObject是NeXTStep对象的缩写。这点现如今已经不是特别重要了。因为他完全是OpenStep的。(译者注:更多关于OpenStep的信息可以在wikipedia检索到)
      • Inheritance is specified as Class: Parent, as seen with Fraction: NSObject.
      • 继承关系的表达:类名:基类名;正如上面的:Fraction:NSObject.
      • Instance variables go between @interface Class: Parent { .... }
      • 类的实例变量写在@interface Class: Parent { .... }中的大括号之间。
      • No access is set (protected, public, private). Default is protected. Setting the access will be shown later
      • 上述代码中没有指明访问权限(protected, public或者private).缺省情况下为protected。我们将在后面讲述如何进行权限设置。
      • Instance methods follow after the member variables. The format is: scope (returnType) methodName: (parameter1Type) parameter1Name;
      • 实例方法写在成员变量的括号之后。格式为:范围(返回值类型) 方法名称:(参数1的类型)参数1;
        1. scope refers to class or instance. instance methods begin with - class level methods begin with+
        2. 其中范围指的是该方式为类的方法还是实例的方法。实例方法以-开始;类得方法以+开始。
      • Interface ends with @end
      • 类的定义以@end结束

o   @implementation

o   类的实现

      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)这本书中的示例程序,经授权使用。
      • Fraction.m
      • Fraction类得实现文件

§  #import "Fraction.h"

§  #import <stdio.h>

§   

§  @implementation Fraction

§  -(void) print {

§      printf( "%i/%i", numerator, denominator );

§  }

§   

§  -(void) setNumerator: (int) n {

§      numerator = n;

§  }

§   

§  -(void) setDenominator: (int) d {

§      denominator = d;

§  }

§   

§  -(int) denominator {

§      return denominator;

§  }

§   

§  -(int) numerator {

§      return numerator;

§  }

§  @end

      • @implementation ClassName starts the implementation @end ends it
      • 类的实现以@implementation 类名 开始;以@end结束
      • All the defined methods are implemented very simlar to how they are declared in the interface
      • 所有类中定义的方法都以与声明时相似的方式加以实现

o   Piecing it together

o   类的定义与实现的结合

      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)这本书中的示例程序,经授权使用。
      • main.m
      • 主程序文件

§  #import <stdio.h>

§  #import "Fraction.h"

§   

§  int main( int argc, const char *argv[] ) {

§      // create a new instance

§      //创建新的实例

§      Fraction *frac = [[Fraction alloc] init];

§   

§      // set the values

§      //设置对象的值

§      [frac setNumerator: 1];

§      [frac setDenominator: 3];

§   

§      // print it

§      //输出对象

§      printf( "The fraction is: " );

§      [frac print];

§      printf( "\n" );

§   

§      // free memory

§      //释放存储空间

§      [frac release];

§   

§      return 0;

§  }

      • output
      • 输出

The fraction is: 1/3

      • Fraction *frac = [[Fraction alloc] init];
      • 关于这一行:Fraction *frac = [[Fraction alloc] init];
        1. There are several important things in this one line.
        2. 这一行中有几点重要的知识。
        3. The way methods in Objective-C are called is [object method], which is similar to object->method() in C++
        4. Objective-C中的方法是通过[对象 方法]的方式来被调用的,这与C++中的 对象->方法 的形式有些类似。
        5. Objective-C doesn't have value types, so there is nothing similar to C++'s: Fraction frac; frac.print();. You always deal with objects as pointers in Objective-C.
        6. Objective-C中不存在值类型,因此不存在类似C++中的:Fraction frac; frac.pring();的写法。在Objective-C中,我们用到的总是指向对象的指针。
        7. What this line is really doing is two things: [Fraction alloc] is calling the alloc method on the Fraction class. This is similar to mallocing memory, because that is all that is done in this operation.
        8. 这行代码真正做的是两件事情:[Fraction alloc]是调用Fraction类的alloc方法,仅完成对象空间的分配。这点类似于C++中的分配空间。
        9. [object init] is the constructor call, which initializes any variables in the object. This method is called on the instance returned from [Fraction alloc]. This operation is so common it's usually just done in one line as Object *var = [[Object alloc] init];
        10. [Object init]是调用构造函数,用来对对象中的变量进行初始化。这个方法是针对[Fracton alloc]返回的对象而调用的。这样的操作很普遍,因此通常被写在一行里面:Object *var = [[Object alloc] init];
      • [frac setNumerator: 1] is quite simple. It's calling the setNumerator method on frac, and passing it the parameter 1.
      • [frac setNumerator: 1]这句比较简单,就是调用frac对象的setNumerator方法,传递的参数为1。
      • Like every c variant, there's a construct for freeing memory. This is done via release, which is inherited from NSObject. This method will be explainted in greater detail later.
      • 和C语言中的对象一样,每个类都有析构函数(译者注:原文描述可能有误:怀疑应该为destruct,而不是construct)用来释放空间。Objective-C中是通过release完成的。release是从NSObject类继承而来的。我们将在后文中对该方法进行详细的描述。

·        The details...

·        更多细节⋯

o   Multiple Parameters

o   多个参数

      • Up until this point I haven't showed any way to specify multiple parameters. It's not as intuitive at first, but it's syntax is a welcome addition from Smalltalk
      • 到目前为止,我们还没有看到指定多个参数的示例。指定多个参数的语法是从Smalltalk语言来的。
      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)这本书中的示例程序,经授权使用。
      • Fraction.h
      • 声明Fraction类的头文件

§  ...

§  -(void) setNumerator: (int) n andDenominator: (int) d;

§  ...

      • Fraction.m
      • Fraction类的实现

§  ...

§  -(void) setNumerator: (int) n andDenominator: (int) d {

§      numerator = n;

§      denominator = d;

§  }

§  ...

      • main.m
      • 主程序文件

§  #import <stdio.h>

§  #import "Fraction.h"

§   

§  int main( int argc, const char *argv[] ) {

§      // create a new instance

§      //创建新的对象

§      Fraction *frac = [[Fraction alloc] init];

§      Fraction *frac2 = [[Fraction alloc] init];

§   

§      // set the values

§      //设置值

§      [frac setNumerator: 1];

§      [frac setDenominator: 3];

§   

§      // combined set

§      //一次设置对象的多个值

§      [frac2 setNumerator: 1 andDenominator: 5];

§   

§      // print it

§      //输出

§      printf( "The fraction is: " );

§      [frac print];

§      printf( "\n" );

§   

§      // print it

§      //输出

§      printf( "Fraction 2 is: " );

§      [frac2 print];

§      printf( "\n" );

§   

§      // free memory

§      //释放存储空间

§      [frac release];

§      [frac2 release];

§   

§      return 0;

§  }

      • output
      • 输出结果:

§  The fraction is: 1/3

§  Fraction 2 is: 1/5

      • The method is actually called setNumerator:andDenominator:
      • 其中用到的方法实际上是:setNumerator:andDenominator:
      • Additional parameters are added the same was as the 2nd, such that you'd have method:label1:label2:label3: and you'd call it with [obj method: param1 label1: param2 label2: param3 label3: param4]
      • 更多的参数是通过和上面第二个参数一样的方式来增加的。例如,我们可以有方法:标签1:标签2:标签3:,其调用的方式为:[对象 方法:参数1 标签1:参数2 标签2 标签2:参数3 标签3:参数4](译者注:上面编号很容易因为引起误会。由于参数1的标签通常都是作为方法名称的最后面的一个或者几个单词,因此在函数名称的冒号后面不需要与之对应的标签。这样以来,上述描述中的标签1实际上是参数2的描述;标签2实际上是对参数3的描述;以此类推。)
      • Labels are optional. It's possible to have a method named method:::. This is done by simply not specifing label names, but just a : to separate the parameters. This is however not advised.
      • 其中的标签是可选的。我们也可以指定方法的名称为:方法:::,也就是不指定标签,只使用:来分隔参数,但是建议不要使用这种方式。

o   Constructors

o   构造函数

      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)中的示例程序,经授权使用。
      • Fraction.h
      • 声明Fraction类的头文件

§  ...

§  -(Fraction*) initWithNumerator: (int) n denominator: (int) d;

§  ...

      • Fraction.m
      • Fraction类的实现文件

§  ...

§  -(Fraction*) initWithNumerator: (int) n denominator: (int) d {

§      self = [super init];

§   

§      if ( self ) {

§          [self setNumerator: n andDenominator: d];

§      }

§   

§      return self;

§  }

§  ...

      • main.m
      • 主程序文件

§  #import <stdio.h>

§  #import "Fraction.h"

§   

§  int main( int argc, const char *argv[] ) {

§      // create a new instance

§      //创建新的对象

§      Fraction *frac = [[Fraction alloc] init];

§      Fraction *frac2 = [[Fraction alloc] init];

§      Fraction *frac3 = [[Fraction alloc] initWithNumerator: 3 denominator: 10];

§   

§      // set the values

§      //设置对象的值

§      [frac setNumerator: 1];

§      [frac setDenominator: 3];

§   

§      // combined set

§      //一次设置对象的多个值

§      [frac2 setNumerator: 1 andDenominator: 5];

§   

§      // print it

§      //输出

§      printf( "The fraction is: " );

§      [frac print];

§      printf( "\n" );

§   

§      printf( "Fraction 2 is: " );

§      [frac2 print];

§      printf( "\n" );

§   

§      printf( "Fraction 3 is: " );

§      [frac3 print];

§      printf( "\n" );

§   

§      // free memory

§      //释放存储空间

§      [frac release];

§      [frac2 release];

§      [frac3 release];

§   

§      return 0;

§  }

      • output
      • 输出

§  The fraction is: 1/3

§  Fraction 2 is: 1/5

§  Fraction 3 is: 3/10

      • @interface declaration is identical to a regular function
      • @interface头文件中的对构造函数的声明和一般的函数是一样的。
      • @implementation shows a new keyword: super
      • 在@implementation实现文件中出现了一个新的关键字:super
        1. Similar to Java, Objective-C only has one parent class.
        2. 和Java类似,在Objective-C中一个类只能有一个父类
        3. Accessing it's super constructor is done through [super init] and this is required for proper inheritance.
        4. 通过[super init]就可以访问父类的构造函数。这样做是必要的,是为了能够正确地实现继承关系。
        5. This returns an instance which you assign to another new keyword, self. Self is similar to this in Java and C++.
        6. 这个对父类构造函数调用的语句返回一个实例,我们把这个实例赋值给另外一个新的关键字self。Self关键字类似于Java或者C++中的this。
      • if ( self ) is the same as if ( self != nil ) to make sure that the super constructor successfully returned a new object. nil is Objective-C's form of NULL from C/C++. This is gotten from including NSObject.
      • if ( self )等同于if ( self != nil ),用来确保父类的构造函数成功地返回了一个对象。Objective-C中的nil相当于C/C++中的NULL,引入NSObject即可使用。
      • After you've initialized the varialbes, you return yourself with return self;
      • 在给变量进行了初始化之后,我们通过return self返回自身的对象。
      • The deafult constructor is -(id) init;
      • 缺省的构造函数为-(id) init;
      • Constructors in Objective-C are technically just "init" methods, they aren't a special construct like they are in C++ and Java.
      • 在Objective-C中构造函数从技术层面上来讲只是进行初始化工作的方法。这点不像在C++或者Java中是作为一个特殊的方法出现的。

o   Access Privledges

o   访问权限

      • The default access is @protected
      • 缺省的访问权限是@protected
      • Java implements this with public/private/protected modifiers infront of methods and variables. Objective-C's approach is much more similar to C++'s for instance variables
      • 在Java中是通过把限定符public/private/protected放置在方法或者变量的前面来进行限制的。Objective-C的方法则更类似于C++中的对实例变量的访问权限的限定。
      • Access.h
      • Access类声明的头文件

§  #import <Foundation/NSObject.h>

§   

§  @interface Access: NSObject {

§  @public

§      int publicVar;

§  @private

§      int privateVar;

§      int privateVar2;

§  @protected

§      int protectedVar;

§  }

§  @end

      • Access.m
      • Access的实现文件

§  #import "Access.h"

§   

§  @implementation Access

§  @end

      • main.m
      • 主程序

§  #import "Access.h"

§  #import <stdio.h>

§   

§  int main( int argc, const char *argv[] ) {

§      Access *a = [[Access alloc] init];

§   

§      // works

§      //下面的语句可以正常工作

§      a->publicVar = 5;

§      printf( "public var: %i\n", a->publicVar );

§   

§      // doesn't compile

§      //下面的语句编译是会报错

§      //a->privateVar = 10;

§      //printf( "private var: %i\n", a->privateVar );

§   

§      [a release];

§      return 0;

§  }

      • output
      • 输出

public var: 5

      • As you an see, instead of private: [list of vars] public: [list of vars] like in C++, it's just @private, @protected, etc.
      • 我们可以看出,我们不是完全使用C++中的 限定符:[变量列表]的方式来表明访问权限的;而是使用:@限定符的方式来进行访问权限的声明。

o   Class level access

o   类级别的访问权限

      • Often it's nice to have class level variables and functions, for instance when keeping track of the times an object has been instanciated.
      • 我们经常还需要类级别的变量和函数。例如,为了跟踪一个类被实例化的次数,我们就需要使用类级别的变量。
      • ClassA.h
      • 声明类ClassA的头文件

§  #import <Foundation/NSObject.h>

§   

§  static int count;

§   

§  @interface ClassA: NSObject

§  +(int) initCount;

§  +(void) initialize;

§  @end

      • ClassA.m
      • 类ClassA的实现文件

§  #import "ClassA.h"

§   

§  @implementation ClassA

§  -(id) init {

§      self = [super init];

§      count++;

§      return self;

§  }

§   

§  +(int) initCount {

§      return count;

§  }

§   

§  +(void) initialize {

§      count = 0;

§  }

§  @end

      • main.m
      • 主程序

§  #import "ClassA.h"

§  #import <stdio.h>

§   

§  int main( int argc, const char *argv[] ) {

§      ClassA *c1 = [[ClassA alloc] init];

§      ClassA *c2 = [[ClassA alloc] init];

§   

§      // print count

§      //输出count的值

§      printf( "ClassA count: %i\n", [ClassA initCount] );

§   

§      ClassA *c3 = [[ClassA alloc] init];

§   

§      // print count again

§      //再次输出count的值

§      printf( "ClassA count: %i\n", [ClassA initCount] );

§   

§      [c1 release];

§      [c2 release];

§      [c3 release];

§   

§      return 0;

§  }

      • output
      • 输出

§  ClassA count: 2

§  ClassA count: 3

      • static int count = 0; This is how the class variable is declared. This is not the ideal place for such a variable. A nicer solution would have been like Java's implementation of static class variables. However this works
      • static int count = 0; 这句就是声明类变量的。这句的位置虽然不是一个很好声明变量地方,但是至少这种方式是可以工作的。更好的解决方式也许应该是像Java中实现静态类变量的方式那样。
      • +(int) initCount; This is the actual method that returns the count. Notice the subtle difference. Instead of using a - infront of the type, a + is used. The + denotes a class level function.
      • +(int) initCount; 这个方法用来返回count的值。请注意这里由一个细微的变化:方法的前面使用的是+,而不是-。其中的+就表示这是一个类的函数。
      • Accessing the variable is no different than member variables, as seen by count++ in the constructor of ClassA.
      • 对于count变量的访问和其他类型的实例变量的方法方式没有什么不同。这点我们在ClassA的构造函数中count++这句就可以看出来。
      • The +(void) initialize method is called when Objective-C starts your program, and it's called for every class. This is a good place to initialize class level variables like our count.
      • 类方法+(void) initialize在Objective-C程序启动的时候就会被调用,而且每个类的这个方法都会被调用。这里是一个很好的可用于对类似诸如count这样的类变量进行初始化的地方。

o   Exceptions

o   异常

      • NOTE: Exception handling is only supported in Mac OS X 10.3
      • 注意:异常处理只有在Mac OS X 10.3上才支持。
      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)中的示例程序,经授权使用。
      • CupWarningException.h
      • 类CupWarningException的声明头文件

§  #import <Foundation/NSException.h>

§   

§  @interface CupWarningException: NSException

§  @end

      • CupWarningException.m
      • 类CupWarningException的实现文件

§  #import "CupWarningException.h"

§   

§  @implementation CupWarningException

§  @end

      • CupOverflowException.h
      • 类CupOverflowException的声明头文件

§  #import <Foundation/NSException.h>

§   

§  @interface CupOverflowException: NSException

§  @end

      • CupOverflowException.m
      • 类CupOverflowException的实现文件

§  #import "CupOverflowException.h"

§   

§  @implementation CupOverflowException

§  @end

      • Cup.h
      • 类Cup的声明头文件

§  #import <Foundation/NSObject.h>

§   

§  @interface Cup: NSObject {

§      int level;

§  }

§   

§  -(int) level;

§  -(void) setLevel: (int) l;

§  -(void) fill;

§  -(void) empty;

§  -(void) print;

§  @end

      • Cup.m
      • 类Cup的实现

§  #import "Cup.h"

§  #import "CupOverflowException.h"

§  #import "CupWarningException.h"

§  #import <Foundation/NSException.h>

§  #import <Foundation/NSString.h>

§   

§  @implementation Cup

§  -(id) init {

§      self = [super init];

§   

§      if ( self ) {

§          [self setLevel: 0];

§      }

§   

§      return self;

§  }

§   

§  -(int) level {

§      return level;

§  }

§   

§  -(void) setLevel: (int) l {

§      level = l;

§   

§      if ( level > 100 ) {

§          // throw overflow

§          //抛出上溢异常

§          NSException *e = [CupOverflowException

§              exceptionWithName: @"CupOverflowException"

§              reason: @"The level is above 100"

§              userInfo: nil];

§          @throw e;

§      } else if ( level >= 50 ) {

§          // throw warning

§          //抛出警告异常

§          NSException *e = [CupWarningException

§              exceptionWithName: @"CupWarningException"

§              reason: @"The level is above or at 50"

§              userInfo: nil];

§          @throw e;

§      } else if ( level < 0 ) {

§          // throw exception

§          //抛出下溢异常

§          NSException *e = [NSException

§              exceptionWithName: @"CupUnderflowException"

§              reason: @"The level is below 0"

§              userInfo: nil];

§          @throw e;

§      }

§  }

§   

§  -(void) fill {

§      [self setLevel: level + 10];

§  }

§   

§  -(void) empty {

§      [self setLevel: level - 10];

§  }

§   

§  -(void) print {

§      printf( "Cup level is: %i\n", level );

§  }

§  @end

      • main.m
      • 主程序

§  #import "Cup.h"

§  #import "CupOverflowException.h"

§  #import "CupWarningException.h"

§  #import <Foundation/NSString.h>

§  #import <Foundation/NSException.h>

§  #import <Foundation/NSAutoreleasePool.h>

§  #import <stdio.h>

§   

§  int main( int argc, const char *argv[] ) {

§      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

§      Cup *cup = [[Cup alloc] init];

§      int i;

§   

§      // this will work

§      // 不抛出任何异常

§      for ( i = 0; i < 4; i++ ) {

§          [cup fill];

§          [cup print];

§      }

§   

§      // this will throw exceptions

§      //下面的代码将抛出异常

§      for ( i = 0; i < 7; i++ ) {

§          @try {

§              [cup fill];

§          } @catch ( CupWarningException *e ) {

§              printf( "%s: ", [[e name] cString] );

§          } @catch ( CupOverflowException *e ) {

§              printf( "%s: ", [[e name] cString] );

§          } @finally {

§              [cup print];

§          }

§      }

§   

§      // throw a generic exception

§      //捕获所有的异常

§      @try {

§          [cup setLevel: -1];

§      } @catch ( NSException *e ) {

§          printf( "%s: %s\n", [[e name] cString], [[e reason] cString] );

§      }

§   

§      // free memory 

§      //释放存储空间

§      [cup release];

§      [pool release];

§  }

      • output
      • 输出

§  Cup level is: 10

§  Cup level is: 20

§  Cup level is: 30

§  Cup level is: 40

§  CupWarningException: Cup level is: 50

§  CupWarningException: Cup level is: 60

§  CupWarningException: Cup level is: 70

§  CupWarningException: Cup level is: 80

§  CupWarningException: Cup level is: 90

§  CupWarningException: Cup level is: 100

§  CupOverflowException: Cup level is: 110

§  CupUnderflowException: The level is below 0

      • NSAutoreleasePool is a memory management class. Don't worry about what this does right now.
      • NSAutoreleasePool是一个用于内存管理的类。这个我们暂时不用关心。
      • Exceptions that are thrown don't have to extend NSException. You can just as easily use an id as well: @catch ( id e ) { ... }
      • 抛出的异常可以不用继承与NSException类。我们可以仅仅简单的使用@catch(id e)就可以了。
      • There is also a finally block, which behaves just like Java's. The contents of a finally block are guaranteed to be called.
      • 上述代码中还有一个finally代码块,这个和java中的类似。finally代码块中的代码不管是否有异常抛出,都是会被执行的。
      • The string as show in Cup.m, @"CupOverflowException", is a constant NSString object. The @ sign is used often in Objective-C to denote extentions to the language. A C string is just like C and C++, "String constant", and is of type char *.
      • 出现在Cup.m中的字符串@"CupOverflowException"是一个常量的NSString 对象。其中的@符号会经常出现在Objective-C中,表示是对语言的扩展。C/C++语言中的字符串是char*类型的,例如"String constant"

·        Inheritance, Polymorphism, and other OOP features

·        继承,多态和其他的面向对象的特性

o   The id type

o   id类型

      • Objective-C has a type called id, that acts in some ways like a void*, though it's meant strictly for objects. Objective-C differs from Java and C++ in that when you call a method on an object, it doesn't need to know the type. That method simply just has
        to exist. This is refered to as message pasing in Objective-C.
      • Objective-C中有一种id的类型,它用起来和void *有些相似。但是他只能用于对象。Objective-C和Java以及C++的一个区别在于:当我们调用一个对象的方法的时候,我们不需要知道对象的类型。只需要这个方法存在即可。这种机制在Objective-C中被称为消息传递。
      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)中的示例程序,经授权使用。
      • Fraction.h
      • 声明Fraction类的头文件

§  #import <Foundation/NSObject.h>

§   

§  @interface Fraction: NSObject {

§      int numerator;

§      int denominator;

§  }

§   

§  -(Fraction*) initWithNumerator: (int) n denominator: (int) d;

§  -(void) print;

§  -(void) setNumerator: (int) d;

§  -(void) setDenominator: (int) d;

§  -(void) setNumerator: (int) n andDenominator: (int) d;

§  -(int) numerator;

§  -(int) denominator;

§  @end

      • Fraction.m
      • Fraction类的实现

§  #import "Fraction.h"

§  #import <stdio.h>

§   

§  @implementation Fraction

§  -(Fraction*) initWithNumerator: (int) n denominator: (int) d {

§      self = [super init];

§   

§      if ( self ) {

§          [self setNumerator: n andDenominator: d];

§      }

§   

§      return self;

§  }

§   

§  -(void) print {

§      printf( "%i / %i", numerator, denominator );

§  }

§   

§  -(void) setNumerator: (int) n {

§      numerator = n;

§  }

§   

§  -(void) setDenominator: (int) d {

§      denominator = d;

§  }

§   

§  -(void) setNumerator: (int) n andDenominator: (int) d {

§      numerator = n;

§      denominator = d;

§  }

§   

§  -(int) denominator {

§      return denominator;

§  }

§   

§  -(int) numerator {

§      return numerator;

§  }

§  @end

      • Complex.h
      • 声明Complex类的头文件

§  #import <Foundation/NSObject.h>

§   

§  @interface Complex: NSObject {

§      double real;

§      double imaginary;

§  }

§   

§  -(Complex*) initWithReal: (double) r andImaginary: (double) i;

§  -(void) setReal: (double) r;

§  -(void) setImaginary: (double) i;

§  -(void) setReal: (double) r andImaginary: (double) i;

§  -(double) real;

§  -(double) imaginary;

§  -(void) print;

§  @end

      • Complex.m
      • Complex类的实现

§  #import "Complex.h"

§  #import <stdio.h>

§   

§  @implementation Complex

§  -(Complex*) initWithReal: (double) r andImaginary: (double) i {

§      self = [super init];

§   

§      if ( self ) {

§          [self setReal: r andImaginary: i];

§      }

§   

§      return self;

§  }

§   

§  -(void) setReal: (double) r {

§      real = r;

§  }

§   

§  -(void) setImaginary: (double) i {

§      imaginary = i;

§  }

§   

§  -(void) setReal: (double) r andImaginary: (double) i {

§      real = r;

§      imaginary = i;

§  }

§   

§  -(double) real {

§      return real;

§  }

§   

§  -(double) imaginary {

§      return imaginary;

§  }

§   

§  -(void) print {

§      printf( "%_f + %_fi", real, imaginary ); 

§  }

§  @end

      • main.m
      • 主程序

§  #import <stdio.h>

§  #import "Fraction.h"

§  #import "Complex.h"

§   

§  int main( int argc, const char *argv[] ) {

§      // create a new instance

§      //创建新对象

§      Fraction *frac = [[Fraction alloc] initWithNumerator: 1 denominator: 10];

§      Complex *comp = [[Complex alloc] initWithReal: 10 andImaginary: 15];

§      id number;

§   

§      // print fraction

§      //输出分数

§      number = frac;

§      printf( "The fraction is: " );

§      [number print];

§      printf( "\n" );

§   

§      // print complex

§      //输出复数

§      number = comp;

§      printf( "The complex number is: " );

§      [number print];

§      printf( "\n" );

§   

§      // free memory

§      //释放存储空间

§      [frac release];

§      [comp release];

§      

§      return 0;

§  }

      • output

§  The fraction is: 1 / 10

§  The complex number is: 10.000000 + 15.000000i

      • There are obvious benefits to this type of dynamic binding. You don't have to know the type of something to call a method on it. If the object responds to a message, it will invoke that method. Lots of nasty casting isn't involved in this either, such as
        in Java to call .intValue() on an integer object would involve casting first, then calling the method.
      • 这种动态类型绑定的方式有个明显的好处:调用一个对象的方法的时候不需要直到这个对象的类型。如果该对象能够响应该消息,则会调用对应的方法。这其中也不需要进行让人头痛的类型转换。而在Java中想要调用一个整型数对象的.intValue()方法的时候,则会先进行类型转换,然后才会调用这个方法。

o   Inheritance

o   继承

      • Based on an example in "Programming in Objective-C," Copyright © 2004 by Sams Publishing. Used with permission
      • 下面的程序段是基于《Programming in Objective-C》(Objective-C 编程) (版权所有 © 2004)中的示例程序,经授权使用。
      • Rectangle.h
      • 声明Rectangle类的头文件

§  #import <Foundation/NSObject.h>

§   

§  @interface Rectangle: NSObject {

§      int width;

§      int height;

§  }

§   

§  -(Rectangle*) initWithWidth: (int) w height: (int) h;

§  -(void) setWidth: (int) w;

§  -(void) setHeight: (int) h;

§  -(void) setWidth: (int) w height: (int) h;

§  -(int) width;

§  -(int) height; 

§  -(void) print;

§  @end

      • Rectangle.m
      • Rectangle类的实现

§  #import "Rectangle.h"

§  #import <stdio.h>

§   

§  @implementation Rectangle

§  -(Rectangle*) initWithWidth: (int) w height: (int) h {

§      self = [super init];

§   

§      if ( self ) {

§          [self setWidth: w height: h];

§      }

§   

§      return self;

§  }

§   

§  -(void) setWidth: (int) w {

§      width = w;

§  }

§   

§  -(void) setHeight: (int) h {

§      height = h;

§  }

§   

§  -(void) setWidth: (int) w height: (int) h {

§      width = w;

§      height = h;

§  }

§   

§  -(int) width {

§      return width;

§  }

§   

§  -(int) height {

§      return  height;

§  }

§   

§  -(void) print {

§      printf( "width = %i, height = %i", width, height ); 

§  }

§  @end

      • Square.h
      • 声明Square类的头文件

§  #import "Rectangle.h"

§   

§  @interface Square: Rectangle

§  -(Square*) initWithSize: (int) s;

§  -(void) setSize: (int) s;

§  -(int) size;

§  @end

      • Square.m
      • Square类的实现

§  #import "Square.h"

§   

§  @implementation Square

§  -(Square*) initWithSize: (int) s {

§      self = [super init];

§   

§      if ( self ) {

§          [self setSize: s];

§      }

§   

§      return self;

§  }

§   

§  -(void) setSize: (int) s {

§      width = s;

§      height = s;

§  }

§   

§  -(int) size {

§      return width;

§  }

§   

§  -(void) setWidth: (int) w {

§      [self setSize: w];

§  }

§   

§  -(void) setHeight: (int) h {

§      [self setSize: h]; 

§  }

§  @end

      • main.m
      • 主程序

§  #import "Square.h"

§  #import "Rectangle.h"

§  #import <stdio.h>

§   

§

抱歉!评论已关闭.