前言
Enum,也就是枚舉,從C語言開始就有了,C++、Java、Objective-C、Swift這些語言,當(dāng)然都有對(duì)應(yīng)的枚舉類型,功能可能有多有少,但是最核心的還是一個(gè)—-規(guī)范的定義代碼中的狀態(tài)、選項(xiàng)等“常量”。
本節(jié)的內(nèi)容就是如何正確的使用枚舉。
狀態(tài)與選項(xiàng)的區(qū)別(states and options)
在用 enum 之前,我個(gè)人覺得,區(qū)分一下狀態(tài)和選項(xiàng)的概念還是很必要的。
狀態(tài),同時(shí)只能有一種,如“ OK ”,“ Error ”,不可能同時(shí)是OK和Error。
選項(xiàng),同時(shí)可以有一種或一種以上,如App可以 同時(shí) 支持橫屏和豎屏,橫屏豎屏在這個(gè)時(shí)候就是“屏幕方向”的兩種不同的選項(xiàng)。
接下來,我們看看如何用枚舉定義狀態(tài)和選項(xiàng)。
enum與狀態(tài)(states)
不好的做法
經(jīng)常看到這樣的寫法:
#define STATE_OK 0
#define STATE_ERROR 1
#define STATE_UNKNOW 2
//直接用int型變量接收
int STATE = STATE_UNKNOW;
這樣做有如下“不恰當(dāng)”:
宏定義沒有類型約束,只是單純的替換。
無法限制狀態(tài)的所有情況,如,認(rèn)為的將STATE賦值成3,程序可能就會(huì)出錯(cuò),找不到匹配的狀態(tài),因?yàn)榫幾g器不會(huì)對(duì)“ STATE = 3; ”提出警告。
正確的做法
typedef enum _TTGState {
TTGStateOK ?= 0,
TTGStateError,
TTGStateUnknow
} TTGState;
//指明枚舉類型
TTGState state = TTGStateOK;
用的時(shí)候就如下:
- (void)dealWithState:(TTGState)state {
switch (state) {
case TTGStateOK:
//...
break;
case TTGStateError:
//...
break;
case TTGStateUnknow:
//...
break;
}
}
enum與選項(xiàng) (options)
選項(xiàng),就是說一個(gè)“選項(xiàng)變量”的類型要能夠同時(shí)表示一個(gè)或多個(gè)組合的選擇,如下例子:
//方向,可同時(shí)支持一個(gè)或多個(gè)方向
typedef enum _TTGDirection {
TTGDirectionNone = 0,
TTGDirectionTop = 1 << 0,
TTGDirectionLeft = 1 << 1,
TTGDirectionRight = 1 << 2,
TTGDirectionBottom = 1 << 3
} TTGDirection;
看,這里的選項(xiàng)是用 位運(yùn)算 的方式定義的,這樣的好處就是,我們的選項(xiàng)變量可以如下表示:
//用“或”運(yùn)算同時(shí)賦值多個(gè)選項(xiàng)
TTGDirection direction = TTGDirectionTop | TTGDirectionLeft | TTGDirectionBottom;
//用“與”運(yùn)算取出對(duì)應(yīng)位
if (direction & TTGDirectionTop) {
NSLog(@"top");
}
if (direction & TTGDirectionLeft) {
NSLog(@"left");
}
if (direction & TTGDirectionRight) {
NSLog(@"right");
}
if (direction & TTGDirectionBottom) {
NSLog(@"bottom");
}
direction變量的實(shí)際內(nèi)存如下:
這樣,用位運(yùn)算,就可以同時(shí)支持多個(gè)值。
enum在Objective-C中的“升級(jí)版”
一般來說,我們不能指定枚舉變量的實(shí)際類型是什么,就是說,我們不知道枚舉最后是int型,還是其他的什么類型。但是從C++ 11開始,我們可以為枚舉指定其實(shí)際的存儲(chǔ)類型,如下語法:
enum TTGState : NSInteger {/*...*/};
但是,我們?cè)诙x枚舉的時(shí)候如何保證兼容性呢?Foundation框架已經(jīng)為我們提供了更加“統(tǒng)一、便捷”的枚舉定義方法,我們重新定義上面的例子:
//NS_ENUM,定義狀態(tài)等普通枚舉
typedef NS_ENUM(NSUInteger, TTGState) {
TTGStateOK = 0,
TTGStateError,
TTGStateUnknow
};
//NS_OPTIONS,定義選項(xiàng)
typedef NS_OPTIONS(NSUInteger, TTGDirection) {
TTGDirectionNone = 0,
TTGDirectionTop = 1 << 0,
TTGDirectionLeft = 1 << 1,
TTGDirectionRight = 1 << 2,
TTGDirectionBottom = 1 << 3
};
所以,在開發(fā)Mac、iOS程序中,最好所有的枚舉都用“ NS_ENUM ”和“ NS_OPTIONS ”定義,保證統(tǒng)一。
總結(jié)
充分的用好枚舉,可以增強(qiáng)代碼的可讀性,減少各種“錯(cuò)誤”,讓代碼更加的規(guī)范。