Swift4 模式, 枚举型

创建: 2018/03/05

完成: 2018/03/05

更新: 2018/03/10 改变标题 [Swift4 模式] -> [Swift4 模式, 枚举型]

         补充RawRepresentable协议

【任务表】TODO 

元组(taple)与switch
 

 模式匹配(pattern matching): 检验构造和值是否一致的处理

 case来使用元组 

 switch的待检验量可以是元组, 所有case列举的实例的型必须一致

switch location { // location: [Int, Int]
    case (1, 1):  // 具体值来匹配
        ...
    case (..<0, 0...): // 匹配元素可以使用范围来判定
        ...
    case (8, _): //匹配元组第一个元素, 第二个无论是什么都成立
        ...
    case (var a, 10): // 需要获取时候直接声明var/let
        ...
    default:
        ...
}

 

 switch里用where 

 ● 可以对case的元组附加条件

 在:前面写

switch sample { // sample: Int
    case 1:
        ...
    case let a where a > 10: // where写在匹配标签和:之间
        ...
    default:
        ...
}

 ● 可用逗号同时罗列多个条件

    如果case里有var/let, 要保证声明的量的值一定会被决定

    绝对可行的方法: 声明的量所有匹配量都带

switch sample { // sample: (Int, Int)
    case (let a, 1), (10, 9) // 错误, (10, 9) 时a无法确定值
        ...
    case (let a, 1), (let a, 9) where a == 10: // 可以, 所有标签都带a, a一定会被决定
        ...
    case let (a, b) where a == b, let (a, b) where a == a*b: // 每一个标签都可以单独带where
        ...
    default: ...
}

 

 switch里用可选型 
switch sample { // sample: (Int?, Int?) = (a, b)
    case (1?, 2?): // a,b都存在且a = 1, b = 2
        ...
    case ((1..<10)?, 12?) // a, b都存在且a属性1..<9, b = 2
        ...
    default:
        ...
}

 ● 带问号表示可能是nil, 非nil时进行下一步

   1?   非nil且为1

   nil   为nil

   _?  非nil, 忽略值

   
   
枚举型

 基本枚举型

  共有型枚举型的一种 

enum 枚举型名 {
    case 枚举型实例 // 多个也可以用,连接
    case ...
   ... }

 例:

enum Sample1 {
    case a
    case b
    case c
    case d
}

enum Sample2 {
    case a, b, c, d
}

 ● 元素可以比较是否相等 ==, !=

 方法定义 

 和其他方法定义一样

enum Sample2: CustomStringConvertible {
    case a, b, c, d
    func getNext() -> Sample2 {
        switch self {
        case .a:
            return .b
        case .b:
            return .c
        case .c:
            return .d
        case .d:
            return .a
        }
    }
    var description: String {
        return "\(self.hashValue)"
    }
}
let myEnumTest2: Sample2 = .a
print(myEnumTest2) // 0
print(myEnumTest2.getNext()) // 1

 

 

 值型枚举型 

 

enum 型名: 实体型 {
    case 元素名 = 值 // 值可以不设定, 具体见下方默认值说明
    ...
}

 ● 所有成员都带同类型的值, 值必须各不相同

 ● 所带型叫实体型(raw type), 值为实体值(raw value)

 ● 实体型可为 各种Int, Float/Double, Bool, 字符串, 这些的组合

 ● 默认值:

  实体型为整数时, 默认第一个第一个为0, 不指定值的为前一个的值+1

             字符串时, 不指定则为元素名的字符串, String("元素名")

  其他型时必须制定值

 ● 获取实体值: rawValue

enum Sample3: Int {
    case a=100, b, c, d
}
let myEnumTest3: Sample3 = .d
print(myEnumTest3.rawValue) // 103

 

 枚举型的构造函数

 静态变量, 静态方法 

 ● 只可定义计算型属性 var sample: Type { get {...} set {...} }

 ● 自带构造函数init?(rawValue:)

Sample.init(rawValue: 1)

 ● 自定义构造函数

  self = 实例

init() {
    self = Sample3.a
}

 ● 静态变量, 静态方法: 开头加 static

   静态变量用作默认值,静态方法用来设定默认值等

   
   
共用型的枚举型
 共用型枚举型  
enum 型名 {
    case 元素名 元组定义  // 可以省略元组定义, 即最简单的枚举型
    ...
}

enum Sample4 {
    case a (String, String)
    case b (Int)
    case c (first: Int, second: String) // 可以带标签
    case d
}

生成实例

let myEnumTest4 = Sample4.a("1", "2")

 ● 元素不能互相比较

  要比较则自己去采用Equalable

 ● 用在switch里时, 可用下两种方法获取值, 两种方法作用相同

case let Sample4.a(str1, str2)

case Sample4.a(let str1, let str2)

 ● 元组可带标签, switch的case里面可以省略标签

   let/var 和标签连用时, 写法注意

case let .(first: a, second: b)

case .(first let a, second let b)

 

 if-case

 ● 不带元组的枚举型(简单枚举型), 值型枚举型可以比较

 ● 共用型枚举型的比较只能用switch, 除非自己采用Equalable

 比较方法

if case模式 = 式, ... { // ,... 相当于where部分
    ...
}

if case .a = p {
    ...
}


if case let .a(x, y) = p {
    ...
}

if case .t(10, let y)? = p { // p不是nil, p.x=10
    ...
}

 ● , ...可以写模式匹配, 条件句, 可选绑定等

 for-in中使用case

 case也可以用在for-in

for case let (a?, 10?) in array { // array: [(Int?, Int?)]
    print("a = \(a)")
}

 ● 和普通for-in一样迭代, 只有满足case才会执行代码块

 采用协议

 可以采用协议

 ● 值型枚举型

 自动采用RawRepresentable, 带有rawValue, init?(rawValue:)

protocol RawRepresentable {
    associatedtype RawValue
    init?(rawValue: Self.RawValue)
    public var rawValue: Self.RawValue { get }
}

 

enum 型: 实体型, 协议1, 协议2,  ... {
    ...
}

 ● 共用型枚举型

enum 型: 协议1, 协议2, ... {
    ...
}

 

 改写自身元组内容的方法(method)  
mutating func sample(x: Int) -> Bool {
    switch self {
    case let .(10, a, b)
     self = .d // 把自己self完全替换为新元素
return a > x ... }

 

 递归的构造体

 ● 在需要递归的case前加上indirect

enum Sample5 {
    indirect case ...:
        ...
    ...
}

 ● 比较多时可以在enum前加上indirect

indirect enum Sample5 {
    case ...:
        ...
    ...
}

 

 可选型与枚举型

 可选型由共用型枚举型定义

public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)
    public init(_ some: Wrapped)
    ...
}

 

以下两用法相同

var sample: Int? = 100


if case let x? = sample { ... } // 不同于if-let: if let x = sample { ... }
if case let .some(x) = sample { ... }

 

   
   
   
模式匹配(pattern matching)
 模式匹配的规则

 略  # TODO: Supply [模式匹配的规则 p186]

 模式匹配运算符

 模式 ~= 受体

 ● 不需要case

   
   
   
   
   
   
   
   
posted @ 2018-03-05 02:02  懒虫哥哥  阅读(136)  评论(0编辑  收藏  举报