文章目录
参考文章:
swift中的枚举,相较于OC,功能更加强大,允许出现更多的值类型,可以封装方法,遵守协议,实现拓展,使用范型
一、功能
1.1 语法示例
enum Movement {
case letf
case right
case top
case bottom
}
1.2 值类型
不同于OC的枚举只能为int型,swift允许的值类型有:
- 整型(Integer)
- 浮点数(Float Point)
- 字符串(String)
- 布尔类型(Boolean)
1.2.1 rawValue和真正的值
rawValue:
如果使用整数为原始值,则每个case的原始值依次自增1。若第一个case没有设置原始值,则默认为0;
当使用字符串作为原始值时,每个case的隐含值是该case的名称。
1.2.2 关联值:
rawValue和关联值二选一互斥,通过规定枚举类型控制
- 枚举类型规定了,就可以调用rawValue
- 如果没规定,就不能在枚举里面赋初始值,但可以是有关联值
如果没在enum里面赋值,如果使用整数为原始值,则每个case的原始值依次自增1。当使用字符串作为原始值时,每个case的隐含值是该case的名称。
枚举中枚举类型要是规定了,就不能用关联值。(规定为string类型,就不能用关联值,注释掉关联值相关就好了)
enum Trade {
case Buy(stock:String,amount:Int)
case Sell(stock:String,amount:Int)
}
let trade = Trade.Buy(stock: "003100", amount: 100)
switch trade {
case .Buy(let stock,let amount):
print("stock:\(stock),amount:\(amount)")
case .Sell(let stock,let amount):
print("stock:\(stock),amount:\(amount)")
default:
()
}
也可以说是枚举的csse可以传值。
而在OC中,需要写专门的方法或用类去封装。
1.2.3 属性
增加一个存储属性到枚举中不被允许,但你依然能够创建计算属性。当然,计算属性的内容都是建立在枚举值下或者枚举关联值得到的。
enum Device {
case iPad, iPhone
var year: Int {
switch self {
case iPhone: return 2007
case iPad: return 2010
}
}
}
这样就不行
1.3 方法
枚举内部允许封装方法,如下所以, 这是一个用于设备介绍的方法。
enum Device {
case iPad, iPhone, AppleTV, AppleWatch
func introduced() -> String {
switch self {
case .iPad: return "iPad"
case .iPhone: return "iPhone"
case .AppleWatch: return "AppleWatch"
case .AppleTV: return "AppleTV"
}
}
}
print(Device.iPhone.introduced())
1.4 协议
protocol CustomStringConvertible {
var description: String { get }
}
enum Trade :CustomStringConvertible{
case Buy(stock:String,amount:Int)
case Sell(stock:String,amount:Int)
var description: String {
switch self {
case .Buy(_, _):
return "Buy"
case .Sell(_, _):
return "Sell"
}
}
}
print(Trade.Buy(stock: "003100", amount: 100).description)
1.5 扩展
枚举也可以进行扩展。最明显的用例就是将枚举的case和method分离,这样阅读你的代码能够简单快速地消化掉enum内容,紧接着转移到方法定义
1.6 泛型
枚举中允许出现范型(例如系统枚举optional,也出现了范型)
二、Demo
通过一段代码展示一下上述所说的功能
实现了一个动物枚举,有🐶 🐱 🦆
鸭子有关联值颜色和位置
遵守animalProtocol协议
嵌套一个animalColor枚举
有一个颜色的属性
有一个获取种类的方法
用扩展为animal添加say方法
实现一个pyrOption的枚举,其中用到了泛型
```c
//协议
protocol animalProtocol {
func run(type: animal) -> String
}
enum animal: animalProtocol {
case dog
case cat
//关联值
case duck(name: String, loaction: String)
//枚举嵌套
enum animalColor: String {
case white,oringe
}
//属性
var color: animalColor {
switch self {
case .dog:
return .white
case .cat:
return .oringe
default:
return .white
}
}
//方法
func getType() -> String {
switch self {
case .dog:
return "dog"
case .cat:
return "cat"
default:
return "other"
}
}
//协议
func run(type: animal) -> String {
return "\(self) run"
}
}
//扩展
extension animal {
func say(pet: animal) -> String {
switch self {
case .dog:
return "dag say:wang wang!"
default:
return "cat say:miao miao!"
}
}
}
//泛型
enum pyrOption<T> {
case none
case some(T)
func getType() -> String {
return "\(T.self)"
}
}
var aPet: animal = .dog
//方法调用
print(aPet.getType())
//协议方法调用
print(aPet.run(type: aPet))
//拓展方法调用
print(aPet.say(pet: aPet))
//属性调用
print(aPet.color)
var bPet: animal = .duck(name: "唐老鸭", loaction: "迪士尼")
//关联值可用于传值
switch bPet {
case .duck(let name, let location):
print("duck \(name) in \(location)")
default:
()
}
//传入类型 获取类型……
print("\(pyrOption<animal>.some(bPet).getType())")
三、Tips
枚举中的方法不能只声明,不实现;
枚举中的属性不能为存储属性;
rawValue和关联值二选一互斥,通过规定枚举类型控制
- 枚举类型规定了,就可以调用rawValue
- 如果没规定,就不能在枚举里面赋初始值,但可以是有关联值
用扩展可以实现case与方法分离(如果需要的话)。
遵守多个协议时,协议之间用,隔开。