#28 初探 enum-Apple 的剪刀石頭布(RPS)範例

隔了幾個禮拜,終於產出一篇作業了!!😭
這陣子真的好忙好忙!!超忙!!
但心裡一直想的是…

我只想沈浸在swift的世界裡啊~

吶喊完了…開始進入正題 →

初探enum

本次作業的重點放在研究enum。enum跟class、struct一樣屬於Swift自訂型別的方式。既然是型別,開頭第一個字母記得要大寫。

enum中文稱為列舉,它可以建立一組相關聯的資料,一條條指定清楚。
基本款長這個樣子:

enum 自訂型別名稱{
case 項目一
case 項目二
case 項目三
}

case 數量可以自己決定。
或是長這樣

enum 自訂型別名稱{
case 項目一, 項目二, 項目三
}

enum出現的時機

同樣的程式結果,可能有許多不同的寫法,例如字串(” ”)很方便,雙引號內打什麼它就呈現什麼,例如:

var drink: String
drink = "大正紅茶拿鐵大杯無糖"
drink = "芋頭鮮奶半糖"
drink = "beer"
drink = "water"

字串是雙面刃,可以隨你輸入,但打錯時也一併接受!
若是用enum:

enum Drink {
case 大正紅茶拿鐵大杯無糖
case 芋頭鮮奶半糖
case beer
case water
}

當你創造好你的enum之後,可以輸入.來取出裡面的資料。就可以取代脆弱的字串囉!圖片例子1~3:

例1
例2
例3

⭐️ enum可以幫助我們把資料限制在我們創造的清單範圍內。

enum跟switch是好朋友

他們都很細心,switch喜歡一條條比對enum裡的資料,比對完所有enum裡的資料,switch還會給好朋友免除輸入default的方便;反之沒比對完,照平時辦理,需輸入default

enum Drink {
case 大正紅茶拿鐵大杯無糖
case 芋頭鮮奶半糖
case beer
case water
}

var favoriteDrink = Drink.beer
//全部比對完時省略default
switch favoriteDrink {
case .大正紅茶拿鐵大杯無糖:
print("for my friend")
case .芋頭鮮奶半糖:
print("for my son")
case .beer:
print("for myself")
case .water:
print("for my wife")
}
enum Drink {
case 大正紅茶拿鐵大杯無糖
case 芋頭鮮奶半糖
case beer
case water
}

var favoriteDrink = Drink.beer
//沒有比對完時,要輸入default
switch favoriteDrink {
case .大正紅茶拿鐵大杯無糖:
print("for my friend")
case .芋頭鮮奶半糖:
print("for my son")
default:
print("Where is my beer?")
}

enum { }裡也可以包含var, if, switch or func 等,特別注意此時 switch 的 self 代表是比對 enum 裡面的資料,用var一定要有return,忘記加會出現“Missing return in getter expected to return ‘String’”

enum Drink {
case 大正紅茶拿鐵大杯無糖
case 芋頭鮮奶半糖
case beer
case water

var drinkInfo: String {
switch self {
case .大正紅茶拿鐵大杯無糖:
return "for my friend"
case .芋頭鮮奶半糖:
return "for my son"
case .beer:
return "for myself"
case .water:
return "for my wife"
}
}
}

用func則看func是否需要有回傳

enum Drink {
case 大正紅茶拿鐵大杯無糖
case 芋頭鮮奶半糖
case beer
case water

func drinkInfo() {
switch self {
case .大正紅茶拿鐵大杯無糖:
print("for my friend")
case .芋頭鮮奶半糖:
print("for my son")
case .beer:
print("for myself ")
case .water:
print("for my wife")
}
}

rawValue(原始值)

enum也可以加上rawValue,在enum名稱後面加上冒號,底下資料加上等號,但全部僅可以包含一種型別(簡單的型別,如數字、字串),意思是同一個enum所有資料的rawValue型別要一致,例如:

enum GameState:String {
case start = "Rock, Paper, Scissors?"
case win = "You Won!"
case tie = "Tie!"
case lose = "🎃 Won!"
}

本次作業用到enum上述的功能。enum的全部功能不只這些,有機會在介紹,我已經快眼冒金星了。

🌟 補充:

在創造rawValue時,若是case名稱跟等號後面rawValue名稱一模一樣時,則等號後面rawValue可以省略不寫,但最上方enum冒號後的型別的類別名稱不能省略,

例如,原本是這樣:

enum FamilyMember:String {
case father= "father"
case mother= "mother"
case sister= "sister"
case brother= "brother"
}

變成

enum FamilyMember:String {
case father
case mother
case sister
case brother
}

這樣swift就明白下面成員有rawValue,而且跟case名稱長得一模一樣了。

本次作業是參考從apple的電子書下載的範例,可參考這一篇:

應用rawValue修改了部分enum的程式碼,把它變得更精簡又不失易讀性,
例如在GameState的部分從原本:

//用enum創造一個叫GameState的型別,底下包含下列四個指定的資料
enum GameState {
case start
case win
case tie
case lose
//創造一個型別為字串的變數,搭配switch使用,切換四種不同資料時的字串變化
var state: String {
//判斷enum自己型別裡的資料要加上self
switch self {
case .start:
return "Rock, Paper, Scissors?"
case .win:
return "You Won!"
case .tie:
return "Tie!"
case .lose:
return "🎃 Won!"
}
}
}

變成

enum GameState:String {
case start = "Rock, Paper, Scissors?"
case win = "You Won!"
case tie = "Tie!"
case lose = "🎃 Won!"
}

Sign的部分從原本:

//用enum創造一個叫Sign的型別,底下包含下列三個指定的資料
enum Sign {
case scissors
case rock
case paper

//創造一個型別為字串的變數,搭配switch使用,因應三種不同資料的變化回傳不同的emoji
var emoji: String {
//判斷enum自己型別裡的資料要加上self
switch self {
case .scissors:
return "✌️"
case .rock:
return "👊"
case .paper:
return "🖐️"
}
}

//在enum型別底下創造一個判斷勝負的func,搭配if跟switch使用,回傳型別是GameState
func result(npcSign: Sign) -> GameState {
if self == npcSign {
return .tie
}

switch self {
case .scissors:
if npcSign == .paper {
return .win
}
case .rock:
if npcSign == .scissors {
return .win
}
case .paper:
if npcSign == .rock {
return .win
}
}
//上述條件以外的回傳,會呼叫GameState型別底下的lose
return .lose
}
}

變成

enum Sign:String {
case scissors = "✌️"
case rock = "👊"
case paper = "🖐️"

func result(npcSign: Sign) -> GameState {
if self == npcSign {
return .tie
}
switch self {
case .scissors:
if npcSign == .paper {
return .win
}
case .rock:
if npcSign == .scissors {
return .win
}
case .paper:
if npcSign == .rock {
return .win
}
}
return .lose
}
}

截圖:

--

--