Swift十七(1: 字面量 2: 匹配模式)

2022-07-19  本文已影响0人  看谷秀

1 字面量协议
2 匹配模式 (可选类型, where)

一: 字面量

1 字面量

1. var age = 10
2. var isRed = false
3. var name = "jack"

上面代码中的10、false、"Jack"就是字面量 ( 通过字面推断变量类型, 并且能初始化对象 )
正常初始化是 例如Person类 var p = Person(), 而字面量可以直接初始对象

2 常见字面量的默认类型 标准库定义的别名

public typealias IntegerLiteralType = Int
public typealias FloatLiteralType = Double
public typealias BooleanLiteralType = Bool
public typealias StringLiteralType = String

Swift自带的绝大部分类型,都支持直接通过字面量进行初始化
可以通过typealias修改字面量的默认类型

3 字面量协议

Bool : ExpressibleByBooleanLiteral
Int : ExpressibleByIntegerLiteral
Float、Double : ExpressibleByIntegerLiteral、ExpressibleByFloatLiteral
Dictionary : ExpressibleByDictionaryLiteral
String : ExpressibleByStringLiteral
Array、Set : ExpressibleByArrayLiteral
Optional : ExpressibleByNilLiteral

// 例如:  ExpressibleByIntegerLiteral协议(Int协议)
public protocol ExpressibleByIntegerLiteral {
    associatedtype IntegerLiteralType : _ExpressibleByBuiltinIntegerLiteral
    init(integerLiteral value: Self.IntegerLiteralType)
}

Swift自带类型之所以能够通过字面量初始化,是因为它们遵守了对应的协议
遵守协议, 实现init方法, 从而初始化对象

4 字面量协议应用

// 例一: 通过Bool字面量, 初始化Int类型
extension Int : ExpressibleByBooleanLiteral {
public init(booleanLiteral value: Bool) { 
    self = value ? 1 : 0 } 
}
var num: Int = true // bool类型初始化 Int
print(num) // 1
// 例二: 通过通过数组 字典字面量, 初始化结构体Point类型
struct Point {
var x = 0.0, y = 0.0
}
// 分别遵守了, 数组和字典的协议
extension Point : ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral {
// 数组协议方法
init(arrayLiteral elements: Double...) {
  guard elements.count > 0 else { return }
  self.x = elements[0]
  guard elements.count > 1 else { return }
  self.y = elements[1] 
}
// 字典协议方法
init(dictionaryLiteral elements: (String, Double)...) {
  for (k, v) in elements {
     if k == "x" { 
         self.x = v
     } else if k == "y" { 
        self.y = v
     }
  } 
 }
}
var p: Point = [10.5, 20.5] // 数组字面量, 初始化结构体
print(p) // Point(x: 10.5, y: 20.5) 
p = ["x" : 11, "y" : 22] // 字典字面量, 初始化结构体
print(p) // Point(x: 11.0, y: 22.0) 
// Double...代表可变数组元素Double类型
// (String, Double)..代表可变字典, 键值对: 字符串: double
二: 模式匹配

1 通配符模式(Wildcard Pattern)

_ 匹配任何值
_? 匹配非nil值

// 通配符模式(Wildcard Pattern)
enum Life { // 定义枚举
     case human(name: String, age: Int?)
     case animal(name: String, age: Int?) 
} 

func check(_ life: Life) {
switch life {
   case .human(let name, _): // 匹配任何值
   print("human", name)
   case .animal(let name, _?): // 不能为nil
   print("animal", name)
   default:
   print("other") }
}
check(.human(name: "Rose", age: 20)) // human Rose
check(.human(name: "Jack", age: nil)) // human Jack
check(.animal(name: "Dog", age: 5)) // animal Dog
check(.animal(name: "Cat", age: nil)) // other 
// 注意最后返回other, age不能为nil, 所以执行default

2 值绑定模式(Value-Binding Pattern)

let point = (3, 2)
switch point {
case let (x, y): 
print("The point is at(\(x),\(y)")
// 3,2分别绑定 x, y

3 元祖模式

let points = [(0, 0), (1, 0), (2, 0)]
for (x, _) in points {
  print(x)
}
let name: String? = "jack"
let age = 18
let info: Any = [1, 2]
switch (name, age, info) {
  case (_?, _ , _ as String):
  print("case")
  default:
  print("default")
}
//  遍历字典
var scores = ["jack" : 98, "rose" : 100, "kate" : 86]
for (name, score) in scores {
   print(name, score)
}

4 枚举case模式

let age = 2
// 1 原来的写法
if age >= 0 && age <= 9 {
   print("[0, 9]") 
}
// 2 枚举Case模式
if case 0...9 = age { // 匹配 age在0到9区间, 同上
   print("[0, 9]") 
}
// 3 guard
guard case 0...9 = age else { return }
print("[0, 9]")
// 4 switch
switch age {
  case 0...9: print("[0, 9]")
  default: break
}
// 数组遍历
let ages: [Int?] = [2, 3, nil, 5]
for case nil in ages {
print("有nil值")
break
} // 有nil值
// 数组元祖
let points = [(1, 0), (2, 1), (3, 0)]
for case let (x, 0) in points {
   print(x)
} // 13

5 可选模式

let age: Int? = 42
if case .some(let x) = age { // 可选项绑定x
  print(x) 
}

if case let x? = age { // 可选项绑定x
  print(x) 
}

let ages: [Int?] = [nil, 2, 3, nil, 5]
for case let age? in ages { // 条件可选项有值, let age 可选绑定解包
   print(age)
}  // 2 3 5

let ages: [Int?] = [nil, 2, 3, nil, 5]
for item in ages { // 遍历
   if let age = item { // 可选绑定 非空打印
      print(age)
   }
} // 跟上面的for,效果是等价的

func check(_ num: Int?) {
    switch num {
    case 2?: print("2")
    case 4?: print("4")
    case 6?: print("6")
    case _?: print("other")
    case _: print("nil") 
    } 
}
check(4) // 4
check(8) // other
check(nil) // nil

5 类型转换模式

is: 判断类型 case is Int:
as: 类型转换 case let n as String
as? 类型转换, 转换成功为可选类型, 转换失败为nil
as! 类型转换, 功能同as? 转换失败crash

补充:
Any : 表示任意类型
AnyObject: 表示任意类类型
AnyClass: 表示类的原类型 typealias AnyClass = AnyObject.Type

let num: Any = 10
let num: Any = "哈哈"
switch num {
     case is Int: // num是否为Int类型
         print("is Int", num) // 虽然真实类型是Int, 但是编译器依然认为num是Any类型
     case let n as String: // 如果num能强转String, 则把num转成n
          print("as string---\(n)")
     default:
          print("啥也不是")
     break
}
// let num: Any = "10" 打印 is Int 10
// let num: Any = "哈哈" 打印 as string---哈哈

6 表达式模式
表达式模式运用在case中

let point = (1, 2)
switch point {
  case (0, 0):
    print("(0, 0) is at the origin.")
  case (-2...2, -2...2):
    print("(\(point.0), \(point.1)) is near the origin.")
  default:
    print("The point is at (\(point.0), \(point.1)).")
} // (1, 2) is near the origin

7 自定义表达式模式
可以通过重载运算符,自定义表达式模式匹配规则

func isEven(_ i: Int) -> Bool { i % 2 == 0 } // 偶数
func isOdd(_ i: Int) -> Bool { i % 2 != 0 } // 基数

extension Int {
  // 1: pattern为case后面的内容 2: value为switch后面的值 
   static func ~= (pattern: (Int) -> Bool, value: Int) -> Bool {
      pattern(value)   // isEven传给pattern age传给value
   } 
}
var age = 9
switch age {
   case isEven:
   print("偶数")
   case isOdd:
   print("奇数")
   default:
   print("其他") 
}

补充: { // 闭包中...} $0 代表第一个参数

   //  需求判断一个字符串, 是否为另一个字符串的前缀
    func hasPrefix1(str: String, pre: String) -> Bool {
        return str.hasPrefix(pre)
    }

    // prefix 是否为前缀字符换,
    func hasPrefix2(_ prefix: String) ->((String) -> Bool) {
//        return { (str: String) -> Bool in 
//           return str.hasPrefix(prefix)
//        }
        
//        { (str: String) -> Bool in
//           str.hasPrefix(prefix)
//        }
        
          {
            $0.hasPrefix(prefix) // 代表第一个参数 str: String
          }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // 需求判断一个字符串, 是否为另一个字符串的前缀
        let isPre = hasPrefix1(str: "123456", pre: "123") // true
        let fn = hasPrefix2("123")("123456") // true
    }

8 where条件

可以使用where为模式匹配增加匹配条件

<1> switch 添加条件语句

var data = (10, "Jack")
switch data {
  case let (age, _) where age > 10:
    print(data.1, "age > 10")
  case let (age, _) where age > 0:
    print(data.1, "age > 0")
  default: break
}

<2> for循环 添加条件语句

var ages = [10, 20, 44, 23, 55]
for age in ages where age > 30 {
   print(age)
}  // 44 55

<3> 协议 添加条件语句

protocol Stackable { associatedtype Element }
protocol Container {
  associatedtype Stack : Stackable where Stack.Element : Equatable
}
// 1 协议 Continer内部的关联类型Stack需要遵守Stackable协议
// 2 关联类型Stack的关联类型Element需要遵守Equatable协议

<4> func方法 添加条件语句

func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> Bool
where S1.Element == S2.Element, S1.Element : Hashable {
   return false
}

<5> 扩展 条件语句

extension Container where Self.Stack.Element : Hashable { }
上一篇 下一篇

猜你喜欢

热点阅读