sunhongyue4500
3/8/2017 - 9:36 AM

TestSwiftEnum.swift

//
//  TestEnum.swift
//  TestSwiftEnum
//
//  Created by Sunhy on 17/3/8.
//  Copyright © 2017年 Sunhy. All rights reserved.
//

import Foundation

// 枚举定义:枚举声明的类型是囊括可能状态的有限集,且可以具有附加值。通过内嵌(nesting),方法(method),关联值(associated values)和模式匹配(pattern matching),枚举可以分层次地定义任何有组织的数据。

protocol CustomStringConvertible {
    var description: String { get }
}

protocol AccountCompatible {
    var remainingFunds: Int { get }
    mutating func addFunds(amount: Int) throws
    mutating func removeFunds(amount: Int) throws
}

class TestEnum {
    enum Movement{
        case Left
        case Right
        case Top
        case Bottom
    }
    
    func test1() {
        let aMov = Movement.Left
        
        if aMov == .Left {
            print("left")
        }
    }
    
    //    原始值支持如下类型
    //    整型(Integer)
    //    浮点数(Float Point)
    //    字符串(String)
    //    布尔类型(Boolean)
    func test2() {
        // 映射到整型
        enum Movement: Int {
            case Left = 0
            case Right = 1
            case Top = 2
            case Bottom = 3
        }
        
        // 同样你可以与字符串一一对应
        enum House: String {
            case Baratheon = "Ours is the Fury"
            case Greyjoy = "We Do Not Sow"
            case Martell = "Unbowed, Unbent, Unbroken"
            case Stark = "Winter is Coming"
            case Tully = "Family, Duty, Honor"
            case Tyrell = "Growing Strong"
        }
        
        // 或者float double都可以(同时注意枚举中的花式unicode)
        enum Constants: Double {
            case π = 3.14159
            case e = 2.71828
            case φ = 1.61803398874
            case λ = 1.30357
        }
        
        // Mercury = 1, Venus = 2, ... Neptune = 8
        enum Planet: Int {
            case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
        }
        
        // North = "North", ... West = "West"
        // 译者注: 这个是swift2.0新增语法
        enum CompassPoint: String {
            case North, South, East, West
        }
        
        enum VNodeFlags : UInt32 {
            case Delete = 0x00000001
            case Write = 0x00000002
            case Extended = 0x00000004
            case Attrib = 0x00000008
            case Link = 0x00000010
            case Rename = 0x00000020
            case Revoke = 0x00000040
            case None = 0x00000080
        }
    }
    
    // 嵌套枚举
    func test3() {
        enum Character {
            enum Weapon {
                case Bow
                case Sword
                case Lance
                case Dagger
            }
            enum Helmet {
                case Wooden
                case Iron
                case Diamond
            }
            case Thief
            case Warrior
            case Knight
        }
        
//        var tt = Character.Weapon.Bow
    }
    
    // 包含枚举 可以在类、结构体中定义枚举
    func test4() {
        struct Character {
            enum CharacterType {
                case Thief
                case Warrior
                case Knight
            }
            enum Weapon {
                case Bow
                case Sword
                case Lance
                case Dagger
            }
            let type: CharacterType
            let weapon: Weapon
        }
        
        let warrior = Character(type: .Warrior, weapon: .Sword)
    }
    
    func test5() {
        enum Trade {
            case Buy(stock: String, amount: Int)
            case Sell(stock: String, amount: Int)
        }
        
        // 元组作为关联值
        enum Trade2 {
            case Buy(String, Int)
            case Sell(String, Int)
        }
    }
    
    // 小例子
    func test6() {
        // 拥有不同值的用例
        enum UserAction {
            case OpenURL(url: NSURL)
            case SwitchProcess(processId: UInt32)
            case Restart(time: NSDate?, intoCommandLine: Bool)
        }
        
        // 假设你在实现一个功能强大的编辑器,这个编辑器允许多重选择,
        // 正如 Sublime Text : https://www.youtube.com/watch?v=i2SVJa2EGIw
        enum Selection {
            case None
            case Single(Range<Int>)
            case Multiple([Range<Int>])
        }
        
        // 或者映射不同的标识码
        enum Barcode {
            case UPCA(numberSystem: Int, manufacturer: Int, product: Int, check: Int)
            case QRCode(productCode: String)
        }
        
        // 又或者假设你在封装一个 C 语言库,正如 Kqeue BSD/Darwin 通知系统:
        // https://www.freebsd.org/cgi/man.cgi?query=kqueue&sektion=2
        enum KqueueEvent {
            case UserEvent(identifier: UInt, fflags: [UInt32], data: Int)
            case ReadFD(fd: UInt, data: Int)
            case WriteFD(fd: UInt, data: Int)
            case VnodeFD(fd: UInt, fflags: [UInt32], data: Int)
            case ErrorEvent(code: UInt, message: String)
        }
        
        // 最后, 一个 RPG 游戏中的所有可穿戴装备可以使用一个枚举来进行映射,
        // 可以为一个装备增加重量和持久两个属性
        // 现在可以仅用一行代码来增加一个"钻石"属性,如此一来我们便可以增加几件新的镶嵌钻石的可穿戴装备
        enum Wearable {
            enum Weight: Int {
                case Light = 1
                case Mid = 4
                case Heavy = 10
            }
            enum Armor: Int {
                case Light = 2
                case Strong = 8
                case Heavy = 20
            }
            case Helmet(weight: Weight, armor: Armor)
            case Breastplate(weight: Weight, armor: Armor)
            case Shield(weight: Weight, armor: Armor)
        }
        let woodenHelmet = Wearable.Helmet(weight: .Light, armor: .Light)
    }
    
    
    // enum中定义方法
    func test7() {
        enum Wearable {
            enum Weight: Int {
                case Light = 1
            }
            enum Armor: Int {
                case Light = 2
            }
            case Helmet(weight: Weight, armor: Armor)
            
            // 定义函数
            func attributes() -> (weight: Int, armor: Int) {
                switch self {
                    case .Helmet(let w, let a): return (weight: w.rawValue * 2, armor: w.rawValue * 4)
                }
            }
        }
        let woodenHelmetProps = Wearable.Helmet(weight: .Light, armor: .Light).attributes()
        print (woodenHelmetProps)
        
        
        enum Device {
            case iPad, iPhone, AppleTV, AppleWatch
            func introduced() -> String {
                switch self {
                    case .AppleTV: return "\(self) was introduced 2006"
                    case .iPhone: return "\(self) was introduced 2007"
                    case .iPad: return "\(self) was introduced 2010"
                    case .AppleWatch: return "\(self) was introduced 2014"
                }
            }
        }
        print (Device.iPhone.introduced())
    }
    
    // test8 枚举中可以创建计算属性,不能添加存储属性
    func test8() {
        enum Device {
            case iPad, iPhone
            var year: Int {
                switch self {
                case .iPhone: return 2007
                case .iPad: return 2010
                }
            }
        }
    }
    
    // 枚举内创建静态方法
    func test9() {
        enum Device {
            case AppleWatch
            static func fromSlang(term: String) -> Device? {
                if term == "iWatch" {
                    return .AppleWatch
                }
                return nil
            }
        }
        print (Device.fromSlang(term: "iWatch")!)
    }
    
    // 可变方法  修改结构体或者枚举内的属性的值得时候
    func test10() {
        enum TriStateSwitch {
            case Off, Low, High
            mutating func next() {
                switch self {
                case .Off:
                    self = .Low
                case .Low:
                    self = .High
                case .High:
                    self = .Off
                }
            }
        }
        var ovenLight = TriStateSwitch.Low
        ovenLight.next()
        // ovenLight 现在等于.On
        ovenLight.next()
        // ovenLight 现在等于.Off
    }
    
    // 小结
    // 枚举声明的类型是囊括可能状态的有限集,且可以具有附加值。通过内嵌(nesting),方法(method),关联值(associated values)和模式匹配(pattern matching),枚举可以分层次地定义任何有组织的数据。
    func test11() {
        enum Trade: CustomStringConvertible {
            case Buy, Sell
            var description: String {
                switch self {
                case .Buy: return "We're buying something"
                case .Sell: return "We're selling something"
                }
            }
        }
        
        let action = Trade.Buy
        print("this action is \(action)")
    }
}