第7章 类

在本章中,你将继续学习如何使用类以及如何编写方法。还将用到以前章节中所学的一些概念,例如程序循环、构造选择和使用表达式。首先,讨论一下将程序分成多个文件,使较大的程序更容易处理。

7.1 分离接口和实现文件

现在,是时候将类的声明和定义放在单独的文件中。

如果正在使用Xcode,可新建一个称为FractionTest的项目。在文件FractionTest.m中键入以下程序。

代码清单7-1主测试程序: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;

}


注意,该文件未包括Fraction类的定义。然而,它确实导入了一个称为Fraction.h的文件。通常,类的声明(即,@interface部分)要放在它自己的名为class.h的文件中。而类的定义(即,@implementation部分)通常放在相同名称的文件中,但扩展名要使用.m。所以,把Fraction类的声明放到Fraction.h文件中,把Fraction类的定义放到Fraction.m文件中。

要在Xcode中完成该工作,在File菜单中选择New File。在左侧窗格中,选择Cocoa。在右上窗格中,选择Objective-C类。现在窗口应该如图7-1所示。

第7章 类 - 图1

图 7-1 Xcode New File菜单

点击Next,键入Fraction.m作为文件名。选中Also Create Fraction.h框。该文件所在的位置应该与FractionTest.m文件的文件夹相同。现在窗口应该如图7-2所示。

第7章 类 - 图2

图 7-2 在项目中添加新类

现在点击Finish。Xcode在项目中添加了两个文件:Fraction.h和Fraction.m。图7-3显示了这两个文件。

在此我们不使用Cocoa,所以将Fraction.h中的


import<Cocoa/Cocoa.h>


一行内容改为


import<Foundation/Foundation.h>


第7章 类 - 图3

图 7-3 Xcode为新类创建了文件

在同一文件中(Fraction.h),现在可输入类的接口部分,如代码清单7-1所示:

代码清单7-1接口文件Fraction.h


//

//Fraction.h

//FractionTest

//

//Created by Steve Kochan on 7/5/08.

//Copyright 2008MyCompanyName.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类的外观特征,它包括两个名为numerator和denominator的实例变量,而且它们都是整数。它还包含6个实例方法:print、setNumerator:、setDenominator:、numerator、denominator和convertToNum。前3个方法不返回值;之后两个方法返回int值;最后一个方法返回double值。setNumerator:和setDenominator:方法各接收一个整型参数。

Fraction类的实现细节位于文件Fraction.m中。

代码清单7-1实现文件:Fraction.m


//

//Fraction.m

//FractionTest

//

//Created by Steve Kochan on 7/5/08.

//Copyright 2008MyCompanyName.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 1.0;

}

@end


注意,使用以下语句将接口文件导入到实现文件中:


import“Fraction.h”


这样做的目的是,使编译器知道为Fraction类声明的类和方法,同时还能确保这两个文件的一致性。还要提醒一下,一般不能(虽然可以这么做)在实现部分重复声明类的实例变量,所以编译器需要从Fraction.h中包含的接口部分获得信息。

需要注意的另一件事是:导入的文件要用一对引号括起来,而不是<Foundation/Foundation.h>中的<和>字符。双引号用于本地文件(你自己创建的文件),本地文件与系统文件相对,并且它们告诉编译器在哪里找到指定的文件。使用双引号,编译器一般会首先在当前目录寻找指定文件,然后再转到其他位置查找。如果有必要,可以指定编译器要查找的实际位置。

下面是这个例子的测试程序,我们已经将它键入文件FractionTest.m中。

代码清单7-1 main测试程序: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包括接口文件Fraction.h,而不包括实现文件Fraction.m。现在,该程序分成了三个独立的文件。对于小程序例子而言,这似乎要花费很多工作,但是,着手处理较大的程序并和其他程序员共享类声明时,这种实用性就会变得十分明显。

现在可以编译并运行程序,方法与以前使用的一样:选择Build菜单中的Build and Go,或者点击主Xcode窗口中的Build and Go图标。

如果使用命令行编译程序,要为Objective-C编辑器提供这两个“m”文件名。如果使用gcc,则命令行可能如下:


gcc-framework Foundation Fraction.m FractionTest.m-o FractionTest


这将构建一个名为FractionTest的可执行文件。下面就是运行该程序的输出:

代码清单7-1输出


The value of myFraction is:

1/3