十九、字面量、模式匹配

字面量

  1. 常見的字面量的默認(rèn)類型(標(biāo)準(zhǔn)庫(kù)中已有定義)
  • public typealias IntergerLiteralType = Int
  • public typealias FloatLiteralType = Double
  • public typealias BooleanLiteralType = Bool
  • public typealias StringLiteralType = String
//可以通過typealias修改字面量的默認(rèn)類型 但不建議修改
typealias FloatLiteralType = Float
typealias IntergerLiteralType = UInt8
var age = 10//UInt8
var height = 1.68//Float
  1. Swift絕大部分類型友浸,都支持直接通過字面量進(jìn)行初始化
  • Bool、Int偏窝、Float收恢、Double、String祭往、Array伦意、Dictionary、Set链沼、Optional等...
字面量協(xié)議
  1. Swift自帶類型之所以能夠通過字面量進(jìn)行初始化默赂,是因?yàn)樗鼈冏袷亓藢?duì)應(yīng)的協(xié)議
  • Bool : ExpressibleByBooleanLiteral
  • Int : ExpressibleByIntegerLiteral
  • Float 、Double : ExpressibleByFloatLiteral括勺、ExpressibleByIntegerLiteral
  • Dictionary : ExpressibleByDictionaryLiteral
  • String : ExpressibleByStringLiteral
  • Array缆八、Set : ExpressibleByArrayLiteral
  • Optional : ExpressibleByNilLiteral
字面量協(xié)議的應(yīng)用
//使用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)

模式匹配

什么是模式?
  • 模式是用于匹配的規(guī)則疾捍,比如Switch的case奈辰、捕捉錯(cuò)誤的catch、if\guard\where\for語(yǔ)句條件等
Swift中的模式
  • 通配符模式(Wildcard Pattern)
  • 標(biāo)識(shí)符模式(Identifier Pattern)
  • 值綁定模式(Value-Binding Pattern)
  • 元組模式(Tuple Pattern)
  • 枚舉case模式(Enumeration case Pattern)
  • 可選模式(Optional Pattern)
  • 類型轉(zhuǎn)換模式(Type-Casting Pattern)
  • 表達(dá)式模式(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. 通配符模式標(biāo)識(shí)符模式
  • 給對(duì)應(yīng)的變量\常量名賦值
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 該語(yǔ)句需要在函數(shù)中使用
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中的每個(gè)元素和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語(yǔ)句等價(jià)于 只有一個(gè)case的switch語(yǔ)句
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)
}

//與上面的效果是等價(jià)的
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. 類型轉(zhuǎn)換模式
let num :Any = 6
switch num {
case is Int:
    //編譯器依然認(rèn)為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強(qiáng)轉(zhuǎn)為Dog類型 
        dog.eat()
        dog.run()
    case is Cat:
        animal.eat()
        animal.jump()//報(bào)錯(cuò) animal會(huì)被認(rèn)為是Animal實(shí)例
        //(animal as? Cat)?.jump()
    default:
        break
    }
}

var ani = Animal()
check(ani)
var dog = Dog()
check(dog)
var cat = Cat()
check(cat)
  1. 表達(dá)式模式
  • 表達(dá)式模式用在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
自定義表達(dá)式模式
  • 可以通過重載運(yùn)算符,自定義表達(dá)式模式的匹配規(guī)則
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結(jié)尾")
default:
    break
}//以J開頭瑟啃,以k結(jié)尾
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("偶數(shù)")
case isOdd:
    print("奇數(shù)")
default:
    print("其他")
}//奇數(shù)
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{
    
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末论泛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蛹屿,更是在濱河造成了極大的恐慌屁奏,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件错负,死亡現(xiàn)場(chǎng)離奇詭異坟瓢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)犹撒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門折联,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人识颊,你說我怎么就攤上這事诚镰。” “怎么了祥款?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵怕享,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我镰踏,道長(zhǎng)函筋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任奠伪,我火速辦了婚禮跌帐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绊率。我一直安慰自己谨敛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布滤否。 她就那樣靜靜地躺著脸狸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪藐俺。 梳的紋絲不亂的頭發(fā)上炊甲,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音欲芹,去河邊找鬼卿啡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛菱父,可吹牛的內(nèi)容都是我干的颈娜。 我是一名探鬼主播剑逃,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼官辽!你這毒婦竟也來了蛹磺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤同仆,失蹤者是張志新(化名)和其女友劉穎称开,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乓梨,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年清酥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了扶镀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡焰轻,死狀恐怖臭觉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辱志,我是刑警寧澤蝠筑,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站揩懒,受9級(jí)特大地震影響什乙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜已球,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一臣镣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧智亮,春花似錦忆某、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至状原,卻和暖如春聋呢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颠区。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工坝冕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓦呼。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓喂窟,卻偏偏與公主長(zhǎng)得像测暗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子磨澡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容