1. 程式人生 > >Swift- 列舉中的rawValue和hashValue

Swift- 列舉中的rawValue和hashValue

[轉自:http://www.th7.cn/Program/IOS/201411/319644.shtml]

成員值、原始值(符號所代表的內容)、雜湊值:

    1) 成員值和雜湊值的關係:上述的Monday、Tuesday等都是成員值,但是和C語言等不一樣,Swift的成員值不是整型的,Monday等並不代表任何型別,它僅僅是一個符號,因此這裡Monday到Friday並不是整數0 ~ 4,為了安全(防止使用者整型值和成員值亂用)Swift隱藏了這一實現,實際上Swift仍然使用整型值來管理成員值的,Swift使用的是雜湊值,第一個成員值的雜湊值為0,往後依次加1,可以使用Weekdays.Monday.hashValue來訪問成員值所對應的雜湊值,這個雜湊值是不能改變的,由編譯器自動生成,之後不可改變,Swift在背後實際上使用雜湊值來識別列舉符號的(即成員),可以說類似於編譯時作這樣的處理:

#define Monday      0
#define Tuesday     1
#define Thursday    2
#define Friday      3
謹記!成員值僅僅是一組抽象的符號,不能參與任何運算,也不代表任何資料型別!

    2) 成員值僅僅是用來在程式中作為表示的符號,其目的僅僅是為了方便理解程式,但有時候需要給這些符號賦予實際意義,比如在上例中Monday僅僅是一個符號,但是列印的時候想用”一“來代替它,而這個”一“就是Monday所代筆的實際內容,如果直接列印.Monday編譯器是不允許的,因此需要給它定義一個實際意義的值來代表它,而這個就是成員值的預設值了;

    3) 由上述概念的描述可以總結出一旦在定義列舉時指定了原始值之後是再也都無法修改的,因為原始值就是列舉符號的實際內容,比如成員值juice的原始值設為”橙汁",在程式中用juice進行相關操作當然比較方便,但是輸出的時候希望輸出"橙汁"這個實際內容,因此作為juice實際內容的"橙汁"是無法改變,如果改變不僅違反邏輯也違反編譯器的規則(會直接報錯的),同時Swift在語法上也根本不支援改變成員的原始值;

要想定義原始值就必須得給列舉型別指定一種資料型別來讓所有的成員的原始值的型別保持一致,Swift不允許各個成員的原始值的型別不同(因為列舉本身就是指一組意義相似的元素,如果成員的型別都不一樣(有的是Int有的時String)不就違反了這個根本的邏輯原則了,因此Swift語法上要禁止這種情況的發生):

enum WeekDays: String{   
 case Monday = "星期一"  
 case Tuesday = "星期二"    
 case Wednesday = "星期三"   
 case Thursday = "星期四"  
 case Friday = "星期五"}
var day = WeekDays.Mondayprintln(day.rawValue + "好!") // 星期一好!
在這種情況下每個成員值的原始值都必須定義!

    4) 原始值的推斷:在Swift中只有Int型的原始值可以推斷,其餘型別包括Double、String、Character型別都無法在原始值中推斷;

這裡的推斷是指不用給出所有成員值的原始值而只需要給定一部分即可,其餘的原始值Swift可以自動推斷出,但是這裡就只有Int型別的支援原始值推斷,而推斷的方法和C語言的列舉型別一樣:

enum WeekDays: Int{    
 case Monday    
 case Tuesday   
 case Wednesday   
 case Thursday    
 case Friday}
print(WeekDays.Monday.rawValue)
print(WeekDays.Tuesday.rawValue)
print(WeekDays.Wednesday.rawValue)
print(WeekDays.Thursday.rawValue)
print(WeekDays.Friday.rawValue)// 不給出任何原始值,自動推斷為0 1 2 3 4
enum Week: Int{    
 case Monday    
 case Tuesday   
 case Wednesday = 37  
  case Thursday   
  case Friday   
  case Saturday = 23   
  case Sunday}
print(Week.Monday.rawValue)
print(Week.Tuesday.rawValue)
print(Week.Wednesday.rawValue)
print(Week.Thursday.rawValue)
print(Week.Friday.rawValue)
print(Week.Saturday.rawValue)
print(Week.Sunday.rawValue)
// 0 1 37 38 39 23 24
// 第一個給出指定原始值之前的從0開始計// 所有給出原始值的,從給出的值開始往後加1// 遇到新的給出的原始值重新計算