10.4 枚举数据类型
Objective-C语言使得你可以将一系列值指派给一个变量。枚举数据类型的定义以关键字enum开头,之后是枚举数据类型的名称,然后是标识符序列(包含在一对花括号内),它们定义了可以给该类型指派的所有允许值。例如,语句
enum flag{false, true};
定义了一个数据类型flag。从理论上说,在程序中这个数据类型只能指派true和false两种值,不能指派其他值。遗憾的是,即使违背了这个规则,Objective-C编译器也不会发出警告消息。
要声明一个enum flag类型的变量,仍需要用到关键字enum,之后是枚举类型名称,最后是变量序列。所以语句
enum flag endOfData, matchFound;
定义了两个flag类型的变量endOfData和matchFound。能指派给这两个变量的值只有(理论上是这样)true和false。因此,
endOfData=true;
和
if(matchFound==false)
……
之类的语句都是合法的。
如果希望一个枚举标识符对应一个特定的整数值,那么可以在定义数据类型时给该标识符指定整数值。在列表中依次出现的枚举标识符被指派了以特定整数值开始的序列数。
在定义
enum direction{up, down, left=10,right};
中,定义了一个包含值up、down、left和right的枚举数据类型direction。因为up在序列中位于首位,所以编译器给它赋值为0;down接着up,因此赋给它的值为1;由于left明确指定了一个整数,赋给它值就是10;right的值由列表中前一个enum的值递增得到,因此给它赋的值为11。
枚举标识符可以共享相同的值。例如,
enum boolean{no=0,false=0,yes=1,true=1};
给enum boolean变量指派no和false时,就是向其赋值0,指派yes和true时赋值1。
再举另一个枚举数据类型定义的例子。下面定义了类型enum month。对于这种类型的变量,可以指派的值为一年中十二个月的名字:
enum month{january=1,february, march, april, may, june, july,
august, september, october, november, december};
Objective-C编译器实际上将枚举标识符作为整型常量来处理。如果你的程序包含以下两行enum month thisMonth;
……
thisMonth=february;
那么给thisMonth赋的值是整数2(而不是february这个名字)。
代码清单10-3展示了使用枚举数据类型的简单程序。该程序首先读取一个月份数,然后进入switch语句来判断要进入哪个月份。回忆一下,编译器把枚举值当作整型常量处理,因此它们都是有效的case值。将变量days赋值为该月的天数,在switch退出后显示days的值。程序中包含特定的测试,用来查看该月是否为二月。
代码清单10-3
import<Foundation/Foundation.h>
//print the number of days in a month
int main(int argc, char*argv[])
{
NSAutoreleasePool*pool=[[NSAutoreleasePool alloc]init];
enum month{january=1,february, march, april, may, june,
july, august, september, october, november,
december};
enum month amonth;
int days;
NSLog(@“Enter month number:);
scanf(“i”,&amonth);
switch(amonth){
case january:
case march:
case may:
case july:
case august:
case october:
case december:
days=31;
break;
case april:
case june:
case september:
case november:
days=30;
break;
case february:
days=28;
break;
default:
NSLog(@“bad month number”);
days=0;
break;
}
if(days!=0)
NSLog(@“Number of days is%i”,days);
if(amonth==february)
NSLog(@“…or 29 if its a leap year”);
[pool drain];
return 0;
}
代码清单10-3输出
Enter month number:
5
Number of days is 31
代码清单10-3输出(再次运行)
Enter month number:
2
Number of days is 28
……or 29 if its a leap year
可以明确地给枚举类型的变量指派一个整数值,这应该使用类型转换运算符。因此,如果monthValue是值为6的整型变量,那么表达式
lastMonth=(enum month)(monthValue-1);
是允许的。如果不使用类型转换运算符,编译器也不会有异议(很遗憾)。
使用包含枚举数据类型的程序时,尽量不要依赖枚举值被当作整数这个实事。相反,尽量把它们当作独立的数据类型。枚举类型提供了一种方法,使你能把整数值和有象征意义的名称对应起来。如果以后需要更改这个整数的值,只能在定义枚举的地方更改。如果根据枚举数据类型的实际值进行假设,就丧失了使用枚举带来的好处。
在定义枚举数据类型时,也允许有所变化:可以省略数据类型的名称,定义该类型时,可以将变量声明为特定枚举数据类型中的一个。举出一个同时展示这两种选择的例子,语句
enum{east, west, south, north}direction;
定义了一个(未命名的)枚举数据类型,它包含的值为east、west、south和north,同时还声明了该类型的变量direction。
在代码块中定义的枚举数据类型的作用域限于块的内部。另一方面,在程序的开始及所有块之外定义的枚举数据类型对于该文件是全局的。
定义枚举数据类型时,必须确保枚举标识符与定义在相同作用域之内的变量名和其他标识符不同。