十九、字面量、模式匹配

字面量

  1. 常见的字面量的默认类型(标准库中已有定义)
  • public typealias IntergerLiteralType = Int
  • public typealias FloatLiteralType = Double
  • public typealias BooleanLiteralType = Bool
  • public typealias StringLiteralType = String
//可以通过typealias修改字面量的默认类型 但不建议修改
typealias FloatLiteralType = Float
typealias IntergerLiteralType = UInt8
var age = 10//UInt8
var height = 1.68//Float
  1. Swift绝大部分类型,都支持直接通过字面量进行初始化
  • Bool、Int、Float、Double、String、Array、Dictionary、Set、Optional等...
字面量协议
  1. Swift自带类型之所以能够通过字面量进行初始化,是因为它们遵守了对应的协议
  • Bool : ExpressibleByBooleanLiteral
  • Int : ExpressibleByIntegerLiteral
  • Float 、Double : ExpressibleByFloatLiteral、ExpressibleByIntegerLiteral
  • Dictionary : ExpressibleByDictionaryLiteral
  • String : ExpressibleByStringLiteral
  • Array、Set : ExpressibleByArrayLiteral
  • Optional : ExpressibleByNilLiteral
字面量协议的应用
//使用bool字面量初始化Int类型
extension  Int : ExpressibleByBooleanLiteral{
    public init(booleanLiteral value: Bool) {
        self = value ? 1 : 0
    }
}
var num: Int = true

print(num)//输出: 1
class Student : ExpressibleByIntegerLiteral,ExpressibleByFloatLiteral,ExpressibleByStringLiteral, CustomStringConvertible{
    var name: String = ""
    var score:Double = 0
    required init(floatLiteral value: Double) {
        self.score = value
    }
    required init(stringLiteral value: String) {
        self.name = value
    }
    required init(integerLiteral value: Int) {
        self.score = Double(value)
    }
    required init(unicodeScalarLiteral value: String){
        self.name = value
    }
    required init(extendedGraphemeClusterLiteral value: String){
        self.name = value
    }
    var description: String{
        "name = \(name),score = \(score)"
    }
}

var stu:Student = 90
print(stu)//输出:name = ,score = 90.0
stu = 98.5
print(stu)//输出:name = ,score = 98.5
stu = "Jack"
print(stu)//输出:name = Jack,score = 0.0

struct Point {
    var x = 0.0,y = 0.0
}

extension Point : ExpressibleByArrayLiteral,ExpressibleByDictionaryLiteral{
    typealias Key = String
    
    typealias Value = Double
    
    typealias ArrayLiteralElement = Double
    
    init(arrayLiteral elements: Self.ArrayLiteralElement...) {
        guard elements.count > 0 else {
            return
        }
        self.x = elements[0]

        guard elements.count > 1 else {
            return
        }
        self.y = elements[1]
    }

    
    init(dictionaryLiteral elements: (Self.Key, Self.Value)...) {
        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,30.5]
print(p)//输出:Point(x: 10.5, y: 20.5)
p = ["x" : 11, "y" : 22]
print(p)//输出:Point(x: 11.0, y: 22.0)

模式匹配

什么是模式?
  • 模式是用于匹配的规则,比如Switch的case、捕捉错误的catch、if\guard\where\for语句条件等
Swift中的模式
  • 通配符模式(Wildcard Pattern)
  • 标识符模式(Identifier Pattern)
  • 值绑定模式(Value-Binding Pattern)
  • 元组模式(Tuple Pattern)
  • 枚举case模式(Enumeration case Pattern)
  • 可选模式(Optional Pattern)
  • 类型转换模式(Type-Casting Pattern)
  • 表达式模式(Expression Pattern)
  1. 通配符模式
  • _ 匹配任何值
  • _? 匹配非nil值
enum Life{
    case human(String,Int?)
    case animal(String,Int?)
}

func check(_ life:Life){
    switch life {
    case .human(let name, _)://后面的元素不管
        print("human",name)
    case .animal(let name, _?)://必须为非nil值,但是不使用
        print("animal name",name)
    default:
        print("other")
    }
}

var value1 = Life.human("Jack", nil)
check(value1)//输出:human Jack
value1 = Life.animal("Dog", nil)
check(value1)//输出:other
value1 = Life.animal("Cat", 5)
check(value1)//输出:animal name Cat
  1. 通配符模式标识符模式
  • 给对应的变量\常量名赋值
var value1 = 10
  1. 值绑定模式
let point = (3, 2)
switch point {
case let (x,y):
    print("(\(x), \(y))")
}
  1. 元组模式
let points = [(0, 0), (2, 2), (3, 3)]
for (_,y) in points{
    print(y)
}

let name :String? = "Jack"
let age = 18
let info:Any = [1,2]
switch(name, age, info){
case (_?, _, _ as String):
    print("case")
default:
    print("default")
}

  1. 枚举case模式
let age = 3
//原来的写法
if age >= 0 && age <= 9{
    print("age is [0,9]")
}
//枚举case模式
if case 0...9 = age{
    print("age is [0,9]")
}
//switch
switch age {
case 0...9:
    print("age is [0,9]")
default:
    print("")
}
//guard case 该语句需要在函数中使用
guard case 0...9 = age else {
    return
}
print("age is [0,9]")

let age : [Int?] = [2, 3, nil, 10]
for case nil in age{//age中的每个元素和nil匹配
    print("有nil值")
    break
}

let points = [(1,2),(2,3),(2,0),(3,3)]
for case let (x,0) in points{
    print("\(x)")
}//2

  1. 可选模式
  • if case语句等价于 只有一个case的switch语句
let age: Int? = 42

if case .some(let x) = age {
    print(x)
}

if case let x? = age {
    print(x)
}

let ages:[Int?] = [nil, 2, 3, nil, 5]
for case let age? in ages{
    print(age)
}

//与上面的效果是等价的
for item in ages{
    if  let age = item {
        print(age)
    }
}

func check(_ num:UInt?){
    switch num {
    case (0...5)?:
        print("match in 0...5")
    case _?:
        print("other value, not match in 2...5")
    case _:
        print("nil")
    }
}
check(0)//输出:match in 0...5
check(4)//输出:match in 0...5
check(7)//输出:other value, not match in 2...5
check(nil)//输出:nil
  1. 类型转换模式
let num :Any = 6
switch num {
case is Int:
    //编译器依然认为num是Any类型
    print("is Int",num)
//case let n as Int:
//    print("as Int",n)
default:
    break
}

class Animal {
    func eat() {
        print(type(of: self),"eat")
    }
}

class Dog: Animal {
    func run() {
        print(type(of: self),"run")
    }
}

class Cat: Animal {
    func jump() {
        print(type(of: self),"jump")
    }
}

func check(_ animal:Animal) {
    switch animal {
   case let dog as Dog://将animal强转为Dog类型 
        dog.eat()
        dog.run()
    case is Cat:
        animal.eat()
        animal.jump()//报错 animal会被认为是Animal实例
        //(animal as? Cat)?.jump()
    default:
        break
    }
}

var ani = Animal()
check(ani)
var dog = Dog()
check(dog)
var cat = Cat()
check(cat)
  1. 表达式模式
  • 表达式模式用在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
自定义表达式模式
  • 可以通过重载运算符,自定义表达式模式的匹配规则
struct Student {
    var score = 0,name = ""
    static func ~= (pattern: Int, values: Student) -> Bool {
        values.score >= pattern
    }
    
    static func ~= (pattern: ClosedRange, values: Student) -> Bool {
        pattern.contains(values.score)
    }
    
    static func ~= (pattern: Range, values: Student) -> Bool {
        pattern.contains(values.score)
    }
}

var stu = Student(score: 75, name: "Jack")
switch stu{
case 100:
    print(">= 100")
case 90:
    print(">=90")
case 80..<90:
    print("[80,90)")
case 60...79:
    print("[60,79]")
case 0:
    print(">=0")
default:
    break
}//[60,79]

if case 60 = stu{
    print(">=60")
}//>=60

var info = (Student(score: 70, name: "Jack"),"及格")
switch info{
case let (60, text):
    print(text)
default:
    break
}//及格
extension String{
    static func ~= (pattern: (String) -> Bool, values: String) -> Bool {
            pattern(values)
    }
}

func hasPrefix(_ prefix:String) -> ((String) -> Bool) {
    { $0.hasPrefix(prefix) }
}

func hasSuffix(_ suffix:String) -> ((String) -> Bool) {
    { $0.hasSuffix(suffix) }
}

var str = "Jack"
switch str {
case hasPrefix("J"),hasSuffix("k"):
    print("以J开头,以k结尾")
default:
    break
}//以J开头,以k结尾
func isEven(_ i: Int) -> Bool{
    i % 2 == 0
}

func isOdd(_ i: Int) -> Bool{
    i % 2 != 0
}

extension Int {
    static func ~= (pattern: (Int) -> Bool, value: Int) -> Bool{
        pattern(value)
    }
}
var age = 9

switch age {
case isEven:
    print("偶数")
case isOdd:
    print("奇数")
default:
    print("其他")
}//奇数
prefix operator ~>
prefix operator ~>=
prefix operator ~<
prefix operator ~<=

prefix func ~> (_ i: Int) -> ((Int) -> Bool){
    { $0 > i }
}

prefix func ~>= (_ i: Int) -> ((Int) -> Bool){
    { $0 >= i }
}

prefix func ~< (_ i: Int) -> ((Int) -> Bool){
    { $0 < i }
}

prefix func ~<= (_ i: Int) -> ((Int) -> Bool){
    { $0 <= i }
}

extension Int{
    static func ~= (pattern:(Int) -> Bool,values: Int) -> Bool{
        pattern(values)
    }
}

var age = 9
switch age {
case ~>=0:
    print("1")
case ~>10:
    print("2")
default:
    break
}//1
where
  • 可以使用where为模式匹配增加匹配条件
//以前举过的例子
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
}


var ages = [10, 20, 34, 59]
for age in ages where age > 20{
    print(age)
}

protocol Stackable {
    associatedtype Element
}
protocol Container {
    associatedtype Stack : Stackable where Stack.Element : Equatable
}
func equal(_ s1: S1, _ s2: S2) -> Bool where S1.Element == S2.Element,S1.Element :Equatable{
    return false
}

extension Container where Self.Stack.Element : Hashable{
    
}

你可能感兴趣的:(十九、字面量、模式匹配)