zoukankan      html  css  js  c++  java
  • 关于枚举,你应该了解的东西

    谈到枚举,相信我们大家都并不陌生,大多数编程语言中,都有枚举的实现。关于枚举的定义,我们可以看看这里

    swift 对枚举的进行了更加灵活的实现,比如支持关联值的枚举,还有可以设置原始值的枚举。这都扩展了枚举类型的用途。下面我们就来品味下枚举以及它在 swift 中的实现吧。

    枚举定义语法

    首先,我们来看看在 swift 中定义枚举的语法:

    enum WeekDay {
    
        case Monday
        case Tuesday
        case Wednesday
        case Thursday
        case Friday
        case Saturday
        case Sunday
    
    }
    

    我们注意到,swift 的每个枚举项前面,都使用一个 case 关键字来标识。除了每行声明一个枚举项,也可以将这些枚举项放在一行中声明,每项之间用逗号分隔。

    enum WeekDayInSingleLine {
    
        case Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    
    }
    

    注意一点,Objective-C 和 C 语言那样, swift 中的枚举项不可以用 0,1,2 这样的数字值来代替。它们有自己的值。

    枚举类型定义好之后,我们就可以将它的枚举值赋值给某个变量:

    var weekday = WeekDay.Tuesday
    

    并且,对于类型明确的变量,我们可以直接省去枚举的类型前缀:

    var day:WeekDay = .Wednesday
    

    枚举的使用

    枚举值可以在 switch 语句中进行匹配:

    switch weekday {
    
    case .Monday:
        println(":(")
    case .Tuesday:
        println(":(")
    case .Wednesday:
        println(":(")
    case .Thursday:
        println(":(")
    case .Friday:
        println(":|")
    case .Saturday:
        println(":)")
    case .Sunday:
        println(":)")
    
    }
    

    switch 语句中的每个 case 中,我们提供各个枚举项的名称:.Monday,.Tuesday 等等。在 swift 中 switch 中匹配枚举项,必须显示的列举出所有的枚举项。也就是对于我们上面表示星期的枚举类型 WeekDay, 我们对它的 switch 语句中必须将所有的枚举项分支都明确的写出来。否则就会有编译错误。

    这个机制也体现了 Swift 类型安全的核心思想。如果我们觉得每个枚举项都要明确的指定行为比较麻烦,我们还可以使用 default 分支来对于其余的枚举项定义行为:

    switch weekday {
    
    case .Saturday:
        println(":)")
    case .Sunday:
        println(":)")
    default:
        println(":(")
    
    }
    

    总之,无论用 default 也好,还是明确对每一个枚举项指定行为也好,在 Swift 中,我们都必须对枚举类型下的每个值,指定确定的行为。不能漏掉其中任何一个可能性。

    关联值(Associated Values)

    在 Swift 中,我们还可以定义这样的枚举类型,它的每一个枚举项都有一个附加信息,来扩充这个枚举项的信息表示,这又叫做关联值。加入我们有一个枚举类型 Shape 来表示形状。
    这个形状可以是矩形,也可以是圆形,等等。而每种具体的形状又对应了不同的属性,比如矩形有长,宽,圆形有,圆心,半径,等等。那么枚举的关联值就可以帮我们解决这个问题:

    enum Shape {
    
        case Rectangle(CGRect)
        case Circle(CGPoint,Int)
    
    }
    

    我们看到,每个枚举项的后面,都包含了一对括号,这里面定义了这个枚举项的关联值的类型。对于 Rectangle 我们使用一个 CGRect 来表示他的原点和长宽属性。
    而对于 Circle,我们使用一个包含了 CGPointInt 类型的元组(Tuple) 来表示这个圆的圆心和半径。

    这样我们在初始化枚举类型的时候,我们就可以根据每个枚举项的关联值类型,为它指定附加信息了:

    var rect = Shape.Rectangle(CGRectMake(0, 0, 200, 200))
    var circle = Shape.Circle(CGPointMake(25, 25), 20)
    

    这样的枚举用法,是不是觉得非常方便呢, 有木有脑洞小开的感觉呢,嘿嘿~

    小憩一下,喝杯咖啡 ☕️,我们继续哦。

    ......

    我们再看一下,带有关联值的枚举项在 switch 语句中的用法:

    switch(rect) {
    
    case .Rectangle(let rect):
        println("this is a rectangle at (rect)")
    case let .Circle(center, radius):
        println("this is a circle at (center) with radius (radius)")
    
    }
    

    我们在 case 后面用一对括号来输出枚举项的关联值,可以用 let 或者 var 关键字,分别作为常量和变量进行输出。我们这里这样来使用 case .Rectangle(let rect)。对于关联值是包含多个值的元组类型的,我们可以将 let 关键字放置在枚举项类型的前面,这样就可以不用对每个关联值都声明 let 关键字了,let .Circle(center, radius)。

    原始值(Raw Values)

    我们刚刚了解了关联值类型的枚举的使用,Swift 的枚举类型还提供了另外一个叫做原始值(Raw Values)的实现。和关联值不同,它为枚举项提供一个默认值,这个默认值是在编译的时候就确定的。而不像关联值那样,要再实力化枚举值的时候才能确定。

    这也就是说,原始值对于同一个枚举项都是一样的。而关联值对于同一个枚举项只是值的类型相同,但具体的取值也是不同的。

    下面我们来看一下定义枚举原始值 (Raw Values) 的方法:

    enum WeekDayWithRaw : String {
    
        case Monday = "1. Monday"
        case Tuesday = "2. Tuesday"
        case Wednesday = "3. Wednesday"
        case Thursday = "4. Thursday"
        case Friday = "5. Friday"
        case Saturday = "6. Saturday"
        case Sunday = "7. Sunday"
    
    }
    

    还是表示星期的枚举类型,我们对每个枚举项都定义了一个默认的原始值,注意一下我们定义枚举的第一行代码,enum WeekDayWithRaw : String 我们在枚举定义的最后,多加了一个 String
    关键字,这就表示这个枚举的原始值(Raw Values) 是 String 类型的。

    在我们下面的定义中,也体现了这一点。对于所有的枚举项,我们赋给的原始值都是 String 类型的。

    定义好了原始值后,我们就可以用枚举项的 rawValue 属性来输出它:

    println(WeekDayWithRaw.Saturday.rawValue)  //6. Saturday
    

    我们还可以通过原始值(Raw Values) 来初始化枚举类型:

    let day = WeekDayWithRaw(rawValue: "3. Wednesday")
    

    这个初始化方法的返回值是一个 Optionals。所以我们可以用 Optionals 的组合链来使用它的返回值:

    if let day = WeekDayWithRaw(rawValue: "3. Wednesday") {
        println(day)
    }else{
        println("init fail")
    }
    

    返回值为 Optionals 的类型,代表这个方法可以返回一个具体的值,也可以返回 nil, 因为我们传入初始化方法的原始值,可能会不等于我们预设的那几个值,比如我们这样初始化一个枚举:

    let day = WeekDayWithRaw(rawValue: "No Exist Value")
    

    如上面所示,"No Exist Value" 这个值和我们定义个原始值列表中任何一项都不对应,所以这个初始化是会失败的,在这种情况下初始化方法会返回 nil,来表示初始化失败。

    所以基于这种情况,我们需要对返回值进行判断,这也就是我们上面的 if 判断的用处所在:

    if let day = WeekDayWithRaw(rawValue: "3. Wednesday") {
        println(day)
    }else{
        println("init fail")
    }
    

    关于 Optionals 的更多内容,可以参考 浅谈 Swift 中的 Optionals 这篇文章。

    以上就是我们关于 Swift 中枚举的介绍了,不知各位是否有所收获呢,我们从这个枚举的使用方法中,不难体会到 Swift 中对类型安全 理念的实践,比如 switch 语句中强制的分支实现,以及从原始值初始化的 Optionals 返回值。都体现了这一理念。

    大家还可以在这里下载我们的 playground 文件:

    Enumeration.playground

    更多精彩内容,请扫码关注微信公众号

  • 相关阅读:
    ASP.NET MVC 重点教程一周年版 第二回 UrlRouting
    ASP.NET MVC 重点教程一周年版 第三回 Controller与View
    DynamicData for Asp.net Mvc留言本实例 下篇 更新
    Asp.net MVC视频教程 18 单选与复选框
    使用ASP.NET MVC Futures 中的异步Action
    ASP.NET MVC RC 升级要注意的几点
    ATL、MFC、WTL CString 的今生前世
    msvcprt.lib(MSVCP90.dll) : error LNK2005:已经在libcpmtd.lib(xmutex.obj) 中定义
    关于Windows内存的一些参考文章
    Windows访问令牌相关使用方法
  • 原文地址:https://www.cnblogs.com/theswiftworld/p/swift_enum.html
Copyright © 2011-2022 走看看