十九、字面量、模式匹配

字面量

  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<Int>, values: Student) -> Bool {
        pattern.contains(values.score)
    }
    
    static func ~= (pattern: Range<Int>, 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 : Stackable,S2 : Stackable>(_ s1: S1, _ s2: S2) -> Bool where S1.Element == S2.Element,S1.Element :Equatable{
    return false
}

extension Container where Self.Stack.Element : Hashable{
    
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容