下面简单的介绍枚举这一自定义数据类型的应用
枚举的基本语法
枚举中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)
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)