自定義資料型別 --- 列舉型別全解(swift2.3)
阿新 • • 發佈:2019-02-13
自定義資料型別 — 列舉(swift)
下面簡單的介紹列舉這一自定義資料型別的應用
列舉的基本語法
列舉中rawValue應用
列舉中associatedValue應用
可選型的實質型別就是列舉
列舉的遞迴應用
一:列舉的基礎語法
import UIKit
//: 1.定義一個型別為Month的列舉型別,這個列舉型別有12種可能性
enum Month {
case January,February,March,April,May, June,July,August, September,October,November,December
}
//:2.那麼列舉這種自定義資料型別,可以像類一樣,定義一個變數,這裡可以不需要寫month的資料型別,因為swift會infer month的資料型別為Month
let curMonth = Month.October
//: 3.下面我們定義一個函式,將函式引數的型別設定為我們定義的列舉型別,函式的返回值為String型別
func season( month: Month) ->String{
switch month { //在這裡要注意的是:switch選擇的永遠都是引數的變數名,不是資料型別
case .January: //case 是判斷這個列舉變數是哪一種可能性
return "1"
case .February: //由於switch判斷的是month這個列舉型別的可能性,month一共有12種可能性,我這裡將其一一的列舉出來了,那麼就不需要default 了
return "2"
case .March :
return "3"
case .April :
return "4"
case .May :
return "5"
case .June :
return "6"
case .July :
return "7"
case .August :
return "8"
case .September :
return "9"
case .October :
return "10"
case .November :
return "11"
case .December :
return "12"
}
}
//呼叫剛剛定義的函式,由於這個函式可以傳入一個引數,那麼將Month.October的變數名curMonth傳入進去,來通過函式中的switch來判斷這個列舉變數是哪一種情況
season(curMonth)
二:列舉中rawValue應用
1.通過列舉型別的可能性獲取肯能性的int值
//由於列舉型別的每一種可能性都與一個int型別的整數相互關聯,那麼在函式中,通過引數的點語法的rawValue可以拿到這個列舉變數的rawValue值
// 定義raw value,完全定義
enum Month: Int{//這樣就手動的將Month中的各種可能性和int結合起來了
case January = 1
case February = 2
case March = 3
case April = 4
case May = 5
case June = 6
case July = 7
case August = 8
case September = 9
case October = 10
case November = 11
case December = 12
}
//定義一個函式,計算傳入一個Month變數的引數後,計算出還剩下多少月
func howManyMonthesleft( cruMonth: Month) -> Int{
return 12 - cruMonth.rawValue
}
//定義一個列舉變數
let curMonth = Month.July
//將curMonth作為函式的引數調呼叫,這個簡單的例子說明了列舉型別的可能性可以與int一一對應
howManyMonthesleft(curMonth)
2.通過列舉型別的rawValue獲取肯能性值
//由於列舉型別的每一種可能性都與一個int型別的整數相互關聯,那麼在函式中,通過引數的點語法的rawValue可以拿到這個列舉變數的rawValue值
// 定義raw value,完全定義
enum Month: Int{//這樣就手動的將Month中的各種可能性和int結合起來了
case January = 1
case February = 2
case March = 3
case April = 4
case May = 5
case June = 6
case July = 7
case August = 8
case September = 9
case October = 10
case November = 11
case December = 12
}
//定義一個函式,計算傳入一個Month變數的引數後,計算出還剩下多少月
func howManyMonthesleft( cruMonth: Month) -> Int{
return 12 - cruMonth.rawValue
}
let input = 11
//通過列舉型別的建構函式定義列舉變數,此時定義的變數是一個可選型變數
let curMonth = Month(rawValue: input)
//將curMonth作為函式的引數調呼叫,這個簡單的例子說明了列舉型別的可能性可以與int一一對應
if let curMonth = curMonth{//將可選型curMonth進行解包,得到的是一個Month型別的變數
howManyMonthesleft(curMonth)
}
3.在列舉型別的定義中,也可以沒給可能性繫結int值,這樣系統會自動將各種可能性按0開始編碼
enum Month: Int{//這樣就手動的將Month中的各種可能性和int結合起來了
case January
case February
case March
case April
case May
case June
case July
case August
case September
case October
case November
case December
}
//定義一個函式,計算傳入一個Month變數的引數後,計算出還剩下多少月
func howManyMonthesleft( cruMonth: Month) -> Int{
return 12 - cruMonth.rawValue
}
let input = 11
//通過列舉型別的建構函式定義列舉變數,此時定義的變數是一個可選型變數
let curMonth = Month(rawValue: input)
//將curMonth作為函式的引數調呼叫,這個簡單的例子說明了列舉型別的可能性可以與int一一對應
if let curMonth = curMonth{//將可選型curMonth進行解包,得到的是一個Month型別的變數
howManyMonthesleft(curMonth)//這樣計算出來的值也是對的
}
4.列舉型別的可能性繫結的型別也可以是String型別,不一定都是int型別
// 使用String作為raw value有預設值
enum ProgrammingLanguage2: String{
case Swift = "swift"
case ObjectiveC = "Objective-C"
case C = "c"
case Java = "java"
}
let myFavoriteLanguage2: ProgrammingLanguage2 = .Swift
print( "\(myFavoriteLanguage2.rawValue) is my favorite language.")
三:列舉中associatedValue應用
1.列舉型別中單個關聯值(基本型別關聯值)
// Associate Value 和 Raw value 只能存在一個
enum ATMStatus{//如果是設定列舉變數的Associate Value,就不能設定列舉變數的Raw Value.這裡將列舉型別的各種可以性關聯不同的資料型別
case Success(Int)
case Erro(String)
case Wainting //也可以不關聯任何職
}
//下面我們第一個函式,函式的引數型別為int,放回值為ATMStatus列舉型別
var balance = 1000
func withDraw(amount: Int) -> ATMStatus {
if balance >= amount{
balance -= amount
return .Success(balance)
}else{
return .Erro("your account is not enough")
}
}
//解包的方式有兩種:一種是劉老師說的,一種是Stanford大學白鬍子老頭說的
let result = withDraw(1009)//但是現在返回給我們的還是一個列舉型別的肯能性,那麼需要將可能性裡面的關聯值解包出來
switch result{
case let .Success(newBalance):
print(newBalance)
case let .Erro(newString):
print(newString)
case .Wainting:
print("please wait a minute")
}
//方法二:Stanford大學白鬍子老頭(隨便提一句,解析關聯值不是必須的)
let result1 = withDraw(100)
switch result1{
case .Success(let newBalance):
print(newBalance)
case .Erro(let newString):
print(newString)
case .Wainting:
break
}
2.多個關聯值(可以是tuple型別,也可以是函式型別 —>在Stanford大學有提到)
func multiply(op1: Double, op2: Double) -> Double {
return op1 * op2
}
// Associate Value 和 Raw value 只能存在一個
enum ATMStatus{//如果是設定列舉變數的Associate Value,就不能設定列舉變數的Raw Value.這裡將列舉型別的各種可以性關聯不同的資料型別
case Success(Int)
case Erro(String)
case Wainting //也可以不關聯任何職
}
//下面我們第一個函式,函式的引數型別為int,放回值為ATMStatus列舉型別
var balance = 1000
func withDraw(amount: Int) -> ATMStatus {
if balance >= amount{
balance -= amount
return .Success(balance)
}else{
return .Erro("your account is not enough")
}
}
//解包的方式有兩種:一種是劉老師說的,一種是Stanford大學白鬍子老頭說的
let result = withDraw(1009)//但是現在返回給我們的還是一個列舉型別的肯能性,那麼需要將可能性裡面的關聯值解包出來
switch result{
case let .Success(newBalance):
print(newBalance)
case let .Erro(newString):
print(newString)
case .Wainting:
print("please wait a minute")
}
//方法二:Stanford大學白鬍子老頭(隨便提一句,解析關聯值不是必須的)
let result1 = withDraw(100)
switch result1{
case .Success(let newBalance):
print(newBalance)
case .Erro(let newString):
print(newString)
case .Wainting:
break
}
//定義一個有多個關聯值的列舉型別
enum Shape {
case square( Double)
case rectangle( Double, Double)
case circle( Double, Double, Double)
case simpleOperation(Double ->Double)//sqrt:求一個數的平方根(stanford University)
case point
case multiple((Double,Double) ->Double)
}
//定義這個列舉型別的變數
let rectangle = Shape.rectangle(10, 10) //定義列舉變數的目的是作為函式的引數
let foo = Shape.simpleOperation(sqrt)
let square = Shape.square(20)
let circle = Shape.circle(0, 0, 30)
let point = Shape.point
var result2 = 9.0
var result3 = 10.0
let fooo = Shape.multiple(multiply)
//定義一個函式來計算每一個圖形的面積
func culculateShape(shape: Shape) -> Double {
switch shape {
case .rectangle(let width,let height)://stanford University
return width * height
case let .circle(_, _, radius)://imooc University
return M_PI * radius * radius
case .square(let side):
return side * side
case .simpleOperation(let food):
return food(result2)
case .point:
return 0
case .multiple(let fooo):
return fooo(result2,result3)
}
}
var area = culculateShape(rectangle)
var area1 = culculateShape(square)
var area2 = culculateShape(circle)
var area3 = culculateShape(point)
var resultNumble = culculateShape(foo)//這裡將sqrt函式作為關聯值
var re = culculateShape(fooo)
四:可選型的實質型別就是列舉
var age: Int? = 12
print(age)
age = nil
print(age)
//其實swift內部就是封裝了一個型別名為optional的列舉型,那麼person就是一個列舉型變數
var person = Optional.Some("尹歡一")
person = .None
//那麼在賦值的時候,可以直接賦值
person = "你好,尹歡一"
person = nil
//那麼可選型的解包方法就有兩種
//使用switch解包
switch person{
case .Some(let name):
print(name)
case .None:
print("沒有解包")
}
//2.賦值解包
if let person = person{
print(person)
}else{
print("nil")
}
五:列舉的遞迴應用
// 列舉遞迴,使用indirect關鍵字
enum ArithmeticExpression{
case Number(Int)
indirect case Addition( ArithmeticExpression , ArithmeticExpression )
indirect case Multiplication( ArithmeticExpression , ArithmeticExpression )
}
// 也可以直接將indirect關鍵字放在整個enum前面
indirect enum ArithmeticExpression2{
case Number(Int)
case Addition( ArithmeticExpression , ArithmeticExpression )
case Multiplication( ArithmeticExpression , ArithmeticExpression )
}
// (5 + 4) * 2
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.Addition(five, four)
let two = ArithmeticExpression.Number(2)
let product = ArithmeticExpression.Multiplication(sum, two)
func evaluate(expression: ArithmeticExpression) -> Int {
switch expression {
case .Number(let value):
return value
case .Addition(let left, let right):
return evaluate(left) + evaluate(right)//由於不知道第一次解包出來的是不是一個數,所以在這裡將解包出來的表達是再呼叫這個函式,再進行解析,這樣就實現了遞迴操作
case .Multiplication(let left, let right):
return evaluate(left) * evaluate(right)
}
}
evaluate(product)