Swift 枚举(enumeration)类型总结

Swift 枚举(enumeration)类型总结

枚举类型定义了一组相关值的共同类型,比如东、西、南和北具有的共同类型就是方向,可以定义一个方向的枚举类型,包含它们。枚举类型能够让你在代码中使用类型安全的的值。C语言中的枚举类型是提供了一组整数值和枚举值相对应,但是Swift中的枚举更加灵活,并没有使用响应的整数值。枚举类型中的值称之为原生值(raw value),可以是字符串、字符或者整型和浮点型。
Swift中的枚举类型是一等类型(first-class type),采取了只有类才支持的许多特性,比如计算属性,实例方法等。下面来看看枚举的具体知识点。

枚举语法

Swift的枚举类型比C语言的功能更加强大,在Swift中枚举是一等类型,可以支撑属性和方法。采用enum关键字,定义的主体放在花括号中。
定义语法示例:

    enum enum_name {
        case value1, value2, ...
    }
    或者是: 
    enum enum_name{
        case value1
        case value2
        ...
    }

如果将所有的case都写在一行的话,就只需要一个case;如果写作多行的话,就需要多个case关键字。如:

    enum Method{
        case Add, Sub, Mul, Div
    }
    enum  Method {
        case Add
        case Sub
        case Mul
        case Div
    }

    声明枚举变量:
    var m0: Method = .Add (指定了类型)
    var m1 = Method.Add (没有指定类型时)

由于Swift的类型推断非常强大,它能推断出m0属于Method这个枚举类型的,所以采用“.”运算符的时候可以不写枚举的类型。和C语言不一样的是,当创建枚举类型的时候,Swift并没有提供默认的相应的整数值。比如Add、Sub、Mul和Div不会隐性地被赋值为0,1,2,3。

枚举和switch-case 匹配使用

先来看一个实例:

    func chooseMethod(op: Method) ->(Double, Double) -> Double{
        switch op {
            case .Add:
                // 函数
                func add(a: Double, b: Double) -> Double{
                    return a + b
                }
                return add

            case .Sub:
                // 闭包
                return{
                    (a: Double, b: Double) -> Double in
                    return a - b
                }

            case .Mul:
                // 简写闭包
                return {
                    return $0 * $1
                }

            case .Div:
                // 简写闭包
                return {$0 / $1}
            }

        }
    }
    let val = chooseMethod(.Add)(20,30)
    print(val)

在switch case语句中必须匹配完枚举类型中的所有值,如果没有匹配完,则需要加default 语句。这个实例比较好地阐释了枚举类型和switch-case语句配合使用的具体实现。

枚举类型的原始值

为了兼容C语言,可以将上面的Method定义为:

    enum  Method: Int{
        case Add
        case Sub
        case Mul
        case Div
    }

此时,Add,Sub,Mul和Div默认对应的原始值为0,1,2,3。可以改变某一个枚举值对应的原始值,那么改变的枚举值的后面的枚举值对应的原始值都会改变。如

    enum  Method: Int{
        case Add
        case Sub = 3
        case Mul
        case Div
    }

则此时,Add,Sub,Mul和Div默认对应的原始值为0,3,4,5。可以打印出原始值:

    print(Method.Add.toRaw())

如果原始值的类型不是Int,则应该给每个枚举值都指定对应原始值。

原始值和枚举值的相互转换:
枚举值转化为原始值:toRaw()
原始值转化为枚举值:Method.fromRaw() [该方法返回一个可选值]

枚举的原始值用的场合并不多,仅当了解。

枚举值的关联值

有时候其他类型的值伴随着这些case值一起存储的话会非常有用,你可以定义枚举类型存储任何类型的关联值,如果需要的话,也可以为每个case的值分配不同类型的关联值。比如商品的条形码有一维码和二维码之分,一维码采用UPC格式,由四组数字组成,第一组是0-9,只有一个数,表示数字系统,第二组是由五位数组成,表示生产代码,第三组也是五位数字,产品代码,最后一组由一位数字组成,表示校验码。其他有些产品的条形码采用二维码的形式,它可以编码为字符串。
图片名称 图片名称

我们可以定义这样的枚举类型:

    enum Barcode{
        case upc(Int, Int, Int, Int)
        case qr(String)
    }

我们可以这样理解这个枚举类型:定义了一个名称为Barcode的枚举类型,这个枚举既有一个和(Int, Int, Int, Int)关联值类型关联的值,又有一个和String关联值类型关联的值。就是说它有两个值,一个值和元组类型的值相关联,另一个和String类型的值相关联。这仅仅是定义了这个枚举类型,并没有给它提供任何的实际的值。我们可以这样使用它:

//定义了一个Barcode枚举类型的变量,而这个变量的值是upc,它和
//元组(8, 85909, 51226,3)这个值相关联。
var productCode = Barcode.upc(8, 85909, 51226, 3)
//相同的产品也可以用二维码表示
productCode = .qr("ABCDEFGHIJKLMN")
//这样原来的upc的值以及的它的关联值就被替换为qr和它的关联值了。

枚举类型也是一种数据类型,所以变量或者常量的值只能取这个枚举类型的一个值,如productCode只能是upc或者是qr
那么这个关联值有什么用呢?关联的值只是为了存储额外的信息,所以还是要访问这些额外信息的。如下面具有关联值的枚举类型与switch语句相结合。

switch productCode{

    case .upc(let numberSystem, let manufacturer, let productCode, let check):
        print("UPC: \(numberSystem), \(manufacturer), \(productCode), \(check)")

    case .qr(let productCode):
        print("QR code: \(productCode)")

}

枚举值和一个确定的值对应,则是原始值,如果枚举值和多个值对应,则一般称这多个值为关联值,一般用元组表示。再比如在x轴上的一条线段,它有两种表示方法,一种是给定起点和终点,一种是给定起点和长度(给定终点和长度与此表示方法一致),用枚举表示为:

    enum LineSegment{
        case StartAndEnd(start: Double, end: Double) //后面跟一个元组,下同
        case StartAndLength(start: Double, length: Double)
    }

    使用:
    let line: LineSegment = .StartAndEnd(start: 10, end: 20)
    let line1 = LineSegment.StartAndLength(start: 10, length: 10)

递归枚举

递归枚举是一种将其他枚举实例作为关联值的枚举类型。用关键字indirect表明这个case值是递归的,它告诉编译器来插入所需的间接层。
比如以下的枚举类型:

    enum ArithmeticExpression {

        case number(Int)

        indirect case addition(ArithmeticExpression, ArithmeticExpression)

        indirect case multiplication(ArithmeticExpression, ArithmeticExpression)

    }

也可以将indirect提到enum的前面:

    indirect enum ArithmeticExpression {

        case number(Int)

        case addition(ArithmeticExpression, ArithmeticExpression)

        case multiplication(ArithmeticExpression, ArithmeticExpression)

    }

这个枚举类型存储着三种数学表达式:纯数字、加法表达式和乘法表达式。而加法表达式和乘法表达式又和 ArithmeticExpression类型的值相关联。如下面的使用:

    let five = ArithmeticExpression.number(5)
    let four = ArithmeticExpression.number(4)
    let sum = ArithmeticExpression.addition(five, four)
    let product = ArithmeticExpression.multiplication(sum, .number(2)) // 2 * (4 + 5)

我们可以定义一个函数来计算这个表达式的值:

    func calculate(expression: ArithmeticExpression) -> Int{

        switch expression {

        case .number(let value):
            return value

        case .addition(let add1, let add2):
            return calculate(add1) + calculate(add2)

        case .multiplication(let mul1 , let mul2 ):
            return calculate(mul1) * calculate(mul2)
        }

    }

    print("the result is : \(calculate(product))")
结果为:
the result is : 18
Program ended with exit code: 0
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值