在介绍枚举之前我们先了解一下Swift中 关于面向对象的类型
Swift中不仅提供了
面向过程
的编程支持,也提供了全面的面向对象
的支持,与普通的面向对象的编程语言(只支持类)不同,Swift可以定义枚举,结构体,类 3种面向对象的类型(或swift类型)、这三种类型,都可以被认为是一种该自定义的数据类型,可以被枚举,结构体,类来定义变量,其中枚举
和结构体
是值类型
,使用类
定义的变量则是引用类型
实例和对象的关系
在Swift中,实例和对象是不同的, 只有类的实例
才能成为对象
,而结构体和枚举
的实例
则只能称为 实例
,不能成为对象
在这三种程序单元的内部,分别可以定义属性(存储属性,计算属性)、方法、构造器、下标、嵌套类型(包括嵌套类、嵌套结构体、嵌套枚举)5中类型成员
现在进入正题
1、枚举的定义和特点
Swift中枚举:是一种重新定义的类型:和所有的语言的功能类似
作用:主要用于管理一组有限的值的集合
特点:
1.具有面向对象的特征
2.支持计算属性
3.支持实例方法和类型方法
4.允许枚举遵守指定协议来提供标准的功能
格式:
enum 枚举名 {
//使用case关键字列出所有的枚举值
//枚举的其他成员
}
//枚举的定义
enum Season{
case Spring
case Summer
case Fall
case Winter
}
- 上面枚举中定义了4个枚举值,每个枚举值使用一个case定义
- 我们也可以使用一个case 定义多个枚举值
enum Weekly {
//使用一个case列出多个枚举值
case Monday,Tuesday,Wednesday,Thursday,Firday,Saturday,Sunday
}
2、枚举的使用
与C、OC的枚举不同,Swift的枚举成员不会被分配一个默认的整数值,
【重点】也就是说,Swift的枚举名本身就代表一个枚举实例,对应一个枚举值,与整数值没有任何关系,
定义了Swift的任意类型之后,大致可从如下几个方面来使用该类型
1->声明变量
2->创建实例
3->访问类型属性
4->调用类型方法
5->派生子类。但Swift中 只有类才支持继承,枚举和结构体都不支持继承,因此枚举和结构体都不能派生子类
【注意】:这5中功能,是面向对象的总纲,以后无论学习任何面向对象的编程语言的时候,有了类之后,大致上都是使用上面列出的5种功能
//1->声明
var day:Weekly
//2->创建实例
//使用已有的枚举实例赋值(因为枚举名本身就代表一个枚举实例,所以不需要创建实例)
day = Weekly.Firday
print(day)
- 在定义day的时候已经知道了day的类型 所以在后面使用的时候 可以省略 前面的类型
day = .Firday
3、枚举和Switch语句
【注】因为Switch语言中,Switch语句 必须是
完备
的,也就是说Switch语句的case必须覆盖所有可能的情况,否则最后必须添加default语句
let chooseDay = Weekly.Monday
switch chooseDay {
case .Monday :
print("1")
case .Tuesday:
print("2")
case .Wednesday:
print("3")
case .Thursday :
print("4")
case .Firday:
print("5")
case .Saturday:
print("6")
case .Sunday:
print("7")
}
因为上面程序中的case已经覆盖了 所有枚举值,所以switch语句可以省略,default 分支,当然也可以添加上:只是会报个警告
Default will never be executed
哦,对了 如果 你运行的时候,在switch chooseDay { 这行报警告Switch condition evaluates to a constant
的话,可以把要声明的变量放到函数外
3、原始值
有点类似于,C、OC的枚举,通过原始值可以为每个枚举实例指定一个简单类型,如Int Double String等
语法:enum 枚举名 : 原始值类型 {
case 枚举值 = 原始值
}
- 【注】 Swift并不要对每个枚举值都指定,原始值。
Swift可以根据已指定的原始值,推断出它前后的所有枚举值
- 原始值为:Int 类型
enum weekDay2 :Int {
case Monday=1,Tuesday,Wednesday=5,Thursday,Firday,Saturday,Sunday
}
//可以推断,Tuesday的原始值为2 Thursday=6 Firday=7
原始值为:String类型
Swift也可以为 枚举值分配隐式的原始值--隐式的原始值与变量名同名
这里程序只为Left 显式分配了原始值,意味着只有left的原始值是“Left” 其余的原始值 都是隐式原始值,也就是“Up”,"Down","Right"
【注】枚举要么完全不指定原始值,要么所有枚举都具有原始值,为了让所有的枚举都有原始值,即可让系统自动推断,也可指定显示指定
enum Orientation :String {
case Up ,Down,Left="左",Right
}
现在已经有了 原始值 ,接下来即可使用枚举提供的如下的构造器和属性
init?(rawValue:):可能失败的构造器:根据原始值返回对应的枚举值
hashValue:根据枚举值 获得原始值
let Orient = Orientation.Up
print("\\(Orient.hashValue)")//通过枚举值-->原始值
//输出Up
let MyOrient = Orientation(rawValue:"左") //原始值 --> 枚举值
//因为init?(rawValue:)是一个 可能失败的构造器 所以要执行可选绑定
if let newOrient = MyOrient {
print(newOrient)
}
//输出 Left
print("\\(Orient.hashValue)")//Orient.hashValue 获取哈希值
//输出 0
4、 关联值
枚举除了可以定义一组,枚举成员之外,还可以为枚举成员定义一组关联值,--Swift并不要求各枚举 具有相同的关联值,关联值就是枚举实例携带的一些额外的数据,有点类似于枚举值的属性。
语法: 语法:case 枚举值(元组语法)
enum Planet {
case Mercury (weight:Double ,density:Double,name:String)
case Venus (Double ,Double)
case Jupiter
}
//Mercury Venus携带关联值,而且Mercury的关联值还指定了名称,虽然指定了名称但是,程序依然无法向访问元组成员一样访问关联值
var p1 = Planet.Mercury(weight: 10, density: 10, name: "lpx")
- 【注】:当程序为枚举值 指定了 关联值之后,程序使用这些枚举值的时,必须指定它的关联值。
** 关联值的访问**
- 枚举中的关联值:需要声明额外的变量(常量),并将枚举的关联值绑定到这些变量或常量
//【注】如果程序打算将某个枚举值的所有关联值都提取为变量或常量,也可只将一个var、let 放置在枚举成员的前面。
//eg: case let .Mercury(weight, density, last ):
switch p1 {
//这里就相当于 元组值的绑定
case Planet.Mercury(let weight , let density,let name ):
print("weight= \\(weight) density=\\(density) name=\\(last)")
default :
print("")
}
//输出 weight= 10.0 density=10.0 name=lpx
5、枚举的函数用法(【用的比较少】【而且没有提示】)
对于有关联值的枚举,甚至可以被当做函数使用,该函数总是可以根据关联值创建对应的枚举实例,与普通函数类似的是,可作为函数使用的枚举,也可以被赋值给函数类型的变量,
let fn = Planet.Venus//将Planet.Venus赋给fn变量 得知fn是一个类型为(Double,Double)->Planet的函数
let g1 = fn(10,10)//返回的就是关联值为 10,10的Venus的枚举值与直接获取的Planet.Venus(10, 10)的结果相同
print(g1)
let g2 = Planet.Venus(10, 10)
print(g2)//这两个输出的一样的 Venus(10.0, 10.0)
6、递归枚举
在有些情况下,枚举值所包含的关联值类型 又是该枚举本身,此时就形成了递归枚举,
enum Weekly2 {
indirect case Monday (next:Weekly2)
case Tuesday (String)
case Wednesday
case Thursday
case Firday
indirect case Saturday(next:Weekly2)
case Sunday
}
- Swift也支持用 indirect 修饰枚举本身,把indirect放到enum前面,这就相当于 在每个枚举值的case前都是用了indirect