OK,这一部分是类的学习,以及如何编写方法,是的,我们之前学过如何创建方法,在这里,我们将为方法添加更多的参数,下面我们就开始吧。
我们知道,一个类包含两部分定义,@interface 和 @implementation,这两部分其实可以分成独立的文件存储,我们将创建两个独立的文件 Fraction.h 和 Fraction.m。@interface 位于 Fraction.h 文件中;@implementation 位于 Fraction.m 文件中。
接口文件 Fraction.h
// // Fraction.h // FractionTest // // Created by Steve Kochan on 9/29/10. // Copyright (c) ClassroomM, Inc. All rights reserved. // #import <Foundation/Foundation.h> // The Fraction class @interface Fraction : NSObject { int numerator; int denominator; } -(void) print; -(void) setNumerator: (int) n; -(void) setDenominator: (int) d; -(int) numerator; -(int) denominator; -(double) convertToNum; @end
接口文件告诉编译器 Fraction 类的外观特征。
实现文件 Fraction.m// // Fraction.m // FractionTest // // Created by Steve Kochan on 9/29/10. // Copyright (c) ClassroomM, Inc. All rights reserved. // #import "Fraction.h" @implementation Fraction -(void) print { NSLog (@"%i/%i", numerator, denominator); } -(void) setNumerator: (int) n { numerator = n; } -(void) setDenominator: (int) d { denominator = d; } -(int) numerator { return numerator; } -(int) denominator { return denominator; } -(double) convertToNum { if (denominator != 0) return (double) numerator / denominator; else return NAN; } @end
实现文件用来实现 Fraction 类的实现细节。import "Fraction.h" 用来将接口文件导入到实现文件中。我们注意到 import 这里使用的是双引号,而不是 import <Foundation/Foundation.h> 的尖括号。双引号用于本地文件(我们自己创建的文件)。
测试程序 FractionTest.m
#import "Fraction.h" int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *myFraction = [[Fraction alloc] init]; // set fraction to 1/3 [myFraction setNumerator: 1]; [myFraction setDenominator: 3]; // display the fraction NSLog (@"The value of myFraction is:"); [myFraction print]; [myFraction release]; [pool drain]; return 0; }我们注意到 FractionTest.m 中并没有导入实现文件。
在编写 Java 代码时,一个类的属性一般都会有对应的 getter/setter 方法,一般称为存取方法。OC 2.0 提供了一种简便的方式可自动生成存取方法,它是由 @property 和 @synthesize 两个关键字配合完成的。
@interface Fraction : NSObject { int numerator; int denominator; } @property int numerator, denominator; -(void) print; -(double) convertToNum; @end这里我们并没有为 numerator 和 denominator 属性编写存取方法。
#import "Fraction.h" @implementation Fraction @synthesize numerator, denominator; -(void) print { NSLog (@"%i/%i", numerator, denominator); } -(double) convertToNum { if (denominator != 0) return (double) numerator / denominator; else return NAN; } @end下面这行内容告诉 OC 编译器,为两个实例变量(numerator 和 denominator)生成对应的存取方法:
@synthesize numerator, denominator;通常,存储方法以 set 开头,获取方法以 get 开头,例如 getNumerator、setNumerator。
点运算符(.)在 Java 中很常见,可以用来f访问除私有限定之外的属性和方法,但在 OC 中,目前为止,点运算符只能用来访问属性,这个实在没啥值得说的,[ program ] 这个方式有些邪恶啊。
好了,我们的方法终于可以有多个参数了,说实话,OC 中这种定义方法参数的方式挺让人不适用的,调用时,弄得代码老长,你说这可读性是提高了呢?还是降低了呢?好了,言归正传。
一个同时设置 numerator 和 denominator 的方法可以命名为 setNumerator:andDenominator,形式如下:
[fraction setNumerator: 1 andDenominator: 3]; [fraction setTo: 1 over: 3];
#import <Foundation/Foundation.h> // Define the Fraction class @interface Fraction : NSObject { int numerator; int denominator; } @property int numerator, denominator; -(void) print; -(void) setTo: (int) n over: (int) d; -(double) convertToNum; @end
然后是实现文件
#import "Fraction.h" @implementation Fraction @synthesize numerator, denominator; -(void) print { NSLog (@"%i/%i", numerator, denominator); } -(double) convertToNum { if (denominator != 0) return (double) numerator / denominator; else return NAN; } -(void) setTo: (int) n over: (int) d { numerator = n; denominator = d; } @end
#import "Fraction.h" int main (int argc, char *argv[]) { Fraction *aFraction = [[Fraction alloc] init]; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; [aFraction setTo: 100 over: 200]; [aFraction print]; [aFraction setTo: 1 over: 3]; [aFraction print]; [aFraction release]; [pool drain]; return 0; }
上面的缺点是,当一个方法参数很多时,可读性较差,所以 就有了另外一种编写方式:
-(int) set: (int) n: (int) m
[fraction set 1 : 3];
方法的参数和方法中定义的变量都是局部变量。对于方法参数来说,通过方法传递的任何参数都被复制到局部变量中。因为方法使用参数的副本,所以不能改变通过方法传递的原值。当然,如果参数是对象,那么是可以更改其中实例变量值的。
用 static 声明的变量只在程序开始执行时初始化一次。
static int hitCount = 0;值得注意的是,OC 中的静态变量是可以用在非静态方法中的,这与 Java 是不同的。
self 与 java 的 this 关键字含义是一样的,但 this 在有些情况下是省略的,而 self 却不行,如方法调用:
- (void) add: (Fraction *) f { // To add two fractions: // a/b + c/d = ((a*d) + (b*c)) / (b * d) numerator = numerator * f.denominator + denominator * f.numerator; denominator = denominator * f.denominator; [self reduce]; }
直接上代码:
-(Fraction *) add: (Fraction *) f { // To add two fractions: // a/b + c/d = ((a*d) + (b*c)) / (b * d) // result will store the result of the addition Fraction *result = [[Fraction alloc] init]; result.numerator = numerator * f.denominator + denominator * f.numerator; result.denominator = denominator * f.denominator; [result reduce]; return result; }