Objective-C开发指南--2

    • 异常情况(Exceptions)
      • 注意:异常处理只有 Mac OS X 10.3 以上才支持。
      • 基于 "Programming in Objective-C," Copyright © 2004 by Sams Publishing一书中的范例,并经过允许而刊载。
      • CupWarningException.h

§ #import <Foundation/NSException.h>

§

§ @interface CupWarningException: NSException

@end

      • CupWarningException.m

§ #import "CupWarningException.h"

§

§ @implementation CupWarningException

@end

      • CupOverflowException.h

§ #import <Foundation/NSException.h>

§

§ @interface CupOverflowException: NSException

@end

      • CupOverflowException.m

§ #import "CupOverflowException.h"

§

§ @implementation CupOverflowException

@end

      • Cup.h

§ #import <Foundation/NSObject.h>

§

§ @interface Cup: NSObject {

§ int level;

§ }

§

§ -(int) level;

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

§ -(void) fill;

§ -(void) empty;

§ -(void) print;

@end

      • Cup.m

§ #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 是一个内存管理类别。现在先别管它是干嘛的。
      • Exceptions(异常情况)的丢出不需要扩充(extend)NSException 对象,你可简单的用 id 来代表它: @catch ( id e ) { ... }
      • 还有一个 finally 区块,它的行为就像 Java 的异常处理方式,finally 区块的内容保证会被呼叫。
      • Cup.m 里的 @"CupOverflowException" 是一个 NSString 常数物件。在 Objective-C 中,@ 符号通常用来代表这是语言的衍生部分。C 语言形式的字符串(C string)就像 C/C++ 一样是 "String constant" 的形式,型别为 char *。
  • 继承、多型(Inheritance, Polymorphism)以及其它对象导向功能
    • id 型别
      • Objective-C 有种叫做 id 的型别,它的运作有时候像是 void*,不过它却严格规定只能用在对象。Objective-C 与 Java 跟 C++ 不一样,你在呼叫一个对象的 method 时,并不需要知道这个对象的型别。当然这个 method 一定要存在,这称为 Objective-C 的讯息传递。
      • 基于 "Programming in Objective-C," Copyright © 2004 by Sams Publishing一书中的范例,并经过允许而刊载。
      • Fraction.h

§ #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

§ #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

§ #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

§ #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

      • 这种动态连结有显而易见的好处。你不需要知道你呼叫 method 的那个东西是什么型别,如果这个对象对这个讯息有反应,那就会唤起这个 method。这也不会牵涉到一堆繁琐的转型动作,比如在 Java 里呼叫一个整数对象的 .intValue() 就得先转型,然后才能呼叫这个 method。
    • 继承(Inheritance)
      • 基于 "Programming in Objective-C," Copyright © 2004 by Sams Publishing一书中的范例,并经过允许而刊载。
      • Rectangle.h

§ #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

§ #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

§ #import "Rectangle.h"

§

§ @interface Square: Rectangle

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

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

§ -(int) size;

@end

      • Square.m

§ #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>

§

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

§ Rectangle *rec = [[Rectangle alloc] initWithWidth: 10 height: 20];

§ Square *sq = [[Square alloc] initWithSize: 15];

§

§ // print em

§ printf( "Rectangle: " );

§ [rec print];

§ printf( "\n" );

§

§ printf( "Square: " );

§ [sq print];

§ printf( "\n" );

§

§ // update square

§ [sq setWidth: 20];

§ printf( "Square after change: " );

§ [sq print];

§ printf( "\n" );

§

§ // free memory

§ [rec release];

§ [sq release];

§

§ return 0;

}

      • output

§ Rectangle: width = 10, height = 20

§ Square: width = 15, height = 15

Square after change: width = 20, height = 20

      • 继承在 Objective-C 里比较像 Java。当你扩充你的 super class(所以只能有一个 parent),你想自订这个 super class 的 method,只要简单的在你的 child class implementation 里放上新的实作内容即可。而不需要 C++ 里呆呆的 virtual table。
      • 这里还有一个值得玩味的地方,如果你企图像这样去呼叫 rectangle 的 constructor: Square *sq = [[Square alloc] initWithWidth: 10 height: 15],会发生什么事?答案是会产生一个编译器错误。因为 rectangle constructor 回传的型别是 Rectangle*,而不是 Square*,所以这行不通。在某种情况下如果你真想这样用,使用 id 型别会是很好的选择。如果你想使用 parent 的 constructor,只要把 Rectangle* 回传型别改成 id 即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值