1. 程式人生 > >自定義資料型別 --- 列舉型別全解(swift2.3)

自定義資料型別 --- 列舉型別全解(swift2.3)

自定義資料型別 — 列舉(swift)

下面簡單的介紹列舉這一自定義資料型別的應用

  1. 列舉的基本語法

  2. 列舉中rawValue應用

  3. 列舉中associatedValue應用

  4. 可選型的實質型別就是列舉

  5. 列舉的遞迴應用

一:列舉的基礎語法

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)