枚举入门git
来,小明 给我说说什么是枚举
小明: 你把手举起来
而后呢?
小明: 你看个人手 举没举 ?
复制代码
枚举做为 Swift 的 一等类型
, 咱们正好能够经过枚举, 来 一一列举 Swift 其它 强有力的 类型swift
首先写出枚举的 2种表达方式bash
它们被放在一个大括号里
,纵向排列,互不干扰app
enum SwiftType {
case protocol
case enum
case struct
case class
case tuple
case function
}
复制代码
固然它们也能够抱团相拥在一块儿, 以 逗号
来互相敬畏工具
enum ProgrammingLanguage {
case protocol, enum, struct, class, tuple, function
}
复制代码
掌握以上几种类型,即可呼风唤雨
ui
那么我就以初学者的姿态记录一下枚举吧spa
Swift 的枚举 并不会像 OC 那样固定的赋予一个默认的整形值
,并无所谓的从上到下,原始值
也不是 从0到5debug
它们的原始值(rawValue)
也能够是其它类型code
enum RawValueType {
case 整形
case 字符
case 字符串
case 浮点型
}
复制代码
可是它们必须拥有一个共同的类型
且 原始值惟一
ip
像 ProgrammingLanguage 这种没有指明
原始值类型的枚举 没有原始值,
它们的实例 也无法用点语法 点出 rawValue
若是想像OC 同样 拿到原始值,咱们能够指定类型
enum ProgrammingLanguage: Int {
case Swift
case OC
case Python
case Java
}
复制代码
一旦咱们给定整形,也就意味着它们默认是从0
开始的
下一个枚举的原始值 = 上一个枚举的原始值 + 1
⚠️只有整形是这样 依次累加哦
var p = ProgrammingLanguage.OC.rawValue
print(p)
// 打印 1,由于 Swift 默认是 0
复制代码
如今 咱们作一些改动
enum ProgrammingLanguage: Int {
case Swift = 2
case OC
case Python = 6
case Java
}
var p = ProgrammingLanguage.OC.rawValue
print(p)
// 打印 3,由于 Swift 是 2
print(p1)
// 打印 7,由于 Python 是 6
复制代码
若是咱们指定枚举类型 是 String
,那么其中的 case 对应的rawValue,就是它们的字符串化
enum Song: String {
case 夏日漱石
case 有暖气
}
var s = Song.夏日漱石.rawValue
debugPrint(s)
// 打印 字符串 "夏日漱石"
复制代码
枚举能够经过原始值 rawValue 来初始化
如
enum Drinking: String {
case cola
case sprite
case orangeJuice
}
var dg = Drinking(rawValue: "cola")
# 注意: 这里的dg 是可选型,由于 枚举并不知道 你传进去的 rawValue 是否存在
# 下面会说到,这种方式的实例化 是一个可失败的构造器
复制代码
通常来讲,咱们写出枚举 是为了区分不一样的case,和 OC 同样 Switch
就成了咱们 匹配枚举值的 首选
Swift 的 枚举状况 分为2种
// 登陆方式的枚举
enum LoginWay {
case Apple
case QQ
case Wechat
case Weibo
}
let way = LoginWay.Apple
复制代码
第一种: 穷尽全部
* 遍历全部大括号内的case,一个不漏,不用写defult
* 若是遗漏了,而且没有defult 将会报错
switch way {
case .Apple:
print("apple")
case .QQ:
print("qq")
case .Wechat:
print("wechat")
case .Weibo:
print("weibo")
}
// 打印 "apple"
复制代码
第二种: 投其所好
* 只展现部分我关心的case,其他的 用 defult 表明
* 不用展现所有
switch way {
case .QQ:
print("qq")
case .Weibo:
print("weibo")
default:
print("其它")
}
// 打印 "其它"
复制代码
什么是关联值 ?
咱们来看一个栗子
// 定义一个不一样交通工具 上班时间 ,咱们能够自由选择上班方式
enum OnTheWayTime {
case bicycle(Int) // Int 类型关联值 的 bicycle
case taxi(Int) // Int 类型关联值 的 taxi
case bus(time: Int) // Int 类型关联值 的 bus
case horse(String) // String 类型关联值 的 horse
}
var t = OnTheWayTime.bicycle(60)
// "实例化一个变量",而且给成员变量 bicycle 关联 Int值 60
复制代码
若是咱们想要 改变 t ,也就是咱们的出行方式
在t 的类型已经肯定的状况下,咱们能够不用带枚举名称,直接 .
t = .taxi(30)
咱们去 Switch 遍历 这个枚举,看一下关联值使用方式
switch t {
case .bicycle(let bic):
print("骑自行车上班要 \(bic) 分钟")
case .taxi(let ti):
print("打出租车上班要 \(ti) 分钟")
case .bus(time: let bs):
print("坐公交上班要 \(bs) 分钟")
case .horse(let str):
print("骑马要 \(str)")
}
能够提取关联值 用 "let / var" 修饰
经过值绑定,生成的 "局部变量" 就与 "关联值" 相链接
复制代码
修改t ,再去遍历,t 是能够任意变化的
t = .horse("好久")
打印:骑马要好久
optional(可选型) 是比较经常使用的枚举,它的成员值 .some
也是经过关联值的方式
var age: Int?
age = 17
switch age {
case .none:
print("age 为 nil")
case .some(let value):
print("age 的值是: \(value)")
}
// 打印: age 的值是 17
复制代码
关联值 的成员 有rawValue 吗?
答案是 没有的
由于 rawValue 是听从了 RawRepresentable
协议,协议中经过 associatedtype
来关联 rawValue, associatedtype 是用来定义 在协议中使用的 关联类型
,虽然这个关联类型是不肯定的,可是它们是统一的。
而 有关联值的
枚举,它们的类型是不统一
的,因此没法使用 rawValue
关联以后的成员值 是可变的
原始值的值 从开始 就是肯定的,没法改变
构造过程
:保证新实例在第一次使用前完成正确的初始化
除了在上述中 提到 的 rawValue 初始化
,是一种隐藏了 init?
的可失败的 构造器以外,
咱们还能够自定义 不隐藏的 init?
初始化器
enum Drinking: String {
case cola
case sprite
case orangeJuice
init?(str: String) {
switch str {
case "c":
self = .cola
case "s":
self = .sprite
case "o":
self = .orangeJuice
default:
return nil
}
}
}
下次2种方式均可以完成初始化:
let dg = Drinking(rawValue: "cola")
// print(dg!) cola
let gc = Drinking(str: "s")
// print(gc!) sprite
复制代码
咱们不是列举了全部的状况,case "c","s","o",能够不用在init后面 加 问号吗?能够不加defult 吗?
答案是 不能够的
虽然 咱们列举的case 是 一一俱全的,可是咱们并不能保证 初始化构造的时候 你会传入什么东西
,因此这个构造是可能
会失败的,结果是可选的,因此就得加 ? ,就须要defult来 处理不存在的 case
来,看栗子
吃开封菜的时候到了
经过对 kfc 的点单方式 单点/套餐 咱们写了一个枚举,外界经过调用实例的 description 来得到 描述
enum KFCFood {
case familyFood(Int)
case Other(String, String, String)
var description: String {
switch self {
case .familyFood(let num):
return "今天我一我的吃了 \(num) 个全家桶"
case let .Other(s1, s2, s3):
return "今天晚餐吃了\(s1) \(s2) 还有 \(s3)"
}
}
}
var k = KFCFood.familyFood(2)
print(k.description) // 今天我一我的吃了 2 个全家桶
k = .Other("汉堡", "可乐", "薯条")
print(k.description) // 今天晚餐吃了汉堡 可乐 还有 薯条
ps: 可乐 汉堡 和薯条 不也是套餐吗 你个low 狗
复制代码
咱们定义了一个 KFC 的枚举
经过 关联值 + 计算属性
来 存储 以及 得到 description
switch 里 不须要 defult
case let .Other(s1, s2, s3):
let/var 提到 最前面
咱们也能够 使用协议(Protocols)
和协议扩展(Protocol Extension)
高大上 有没有
经过协议 以及 协议扩展能够更好的 将 成员值 与 属性/方法 实现分离开
, 代码也就天然而然的 通俗易懂了
enum KFCFood {
case familyFood(Int)
case Other(String, String, String)
}
protocol EatFood {
var description: String { get }
}
extension KFCFood: EatFood {
var description: String {
switch self {
case .familyFood(let num):
return "今天我一我的吃了 \(num) 个全家桶"
case let .Other(s1, s2, s3):
return "今天晚餐吃了\(s1) \(s2) 还有 \(s3)"
}
}
}
复制代码
咱们能够像在类中定义方法同样,在枚举中咱们也能够定义方法
enum Song: String {
case chinese
case english
func getName() -> String {
switch self {
case .chinese:
return "chinese"
case.english:
return "english"
}
}
}
let s = Song.chinese
print(s.getName())
// 打印 chinese
复制代码
那么若是咱们想在方法内改变 自身的值呢?
好比 咱们想中文歌 和 英文歌 来回切换
相似这样
enum Song: String {
case chinese
case english
func getChange() {
switch self {
case .chinese:
self = .english
// 切换英文歌
case.english:
self = .chinese
// 切换中文歌
}
}
}
当咱们编译的时候 就会发现 报错了
# Cannot assign to value: 'self' is immutable
复制代码
这个时候咱们就用到 mutating了
在func 前面加上 mutating
,咱们就能够在值类型中 改变自身的值了
参考连接
若是有新的知识 我还会补充进来
以上都是我我的的一些见解,可能有不对的地方
都是第一次学Swift ,还请多多指教!!
复制代码