Swift 語言最小化

PauKohn 7年前發布 | 29K 次閱讀 Swift Apple Swift開發

swift_tour_learning-swift.jpg

在 WWDC 2014 上 Apple Duang!!! 一聲發布了 Swift 。在那次發布會上, Apple 向外界宣布了,自己其實是一家軟件公司。

2015 年, Apple 又 Duang!!! 一聲將 Swift 開源。這讓 Swift 迅速攻占了服務器,這使 Swift 開發 Backend server 成為了可能( Vapor )。

初次接觸 Swift,讓我看到了 Scala、C#、ES 6 的影子,并且語法層面兼容 Objective C。first-class functions 特性讓語言并不局限于 OO,讓 Swift 具有函數式編程語言的表達力。 同時,Swift 作者 Chris Lattner 這位傳奇人物的存在,讓 Swift 成為值得長期投資的一門語言。

變量

Swift 中可以使用 var 和 let 直接定義 變量 或 常量 。

定義變量:

?

var age = 20// 定義變量
let name = "Halo" // 定義常亮
age = 21

聲明類型:

上段代碼看起來有些類似 javascript 若類型語言的特性,Swift 本質上還是強類型的語言,聲明變量的時候,可以指定數據類型:

let cash: Float = 1.25
let money: Double = 1.252525
let dollar: String = "USD"

使用 String

對于字符串,Swift 簡化了 Objective C NSString 的定義方式: @"" :

let currencies = "AUD, " + dollar
let rmb = "1 \(dollar) is 6 RMB"
let formattedString = String(format: "%.2f \(dollar) is about 600 RMB", 100.0) // 100.00 USD is about 600 RMB

\(variable) 是 Swift 為字符串模板提供的支持。不過 Swift 還是支持類似 ES 6 或者 Ruby 中多行字符串模板。多行字符串還是需要 + 號拼接:

let introduceSwift = "We are excited by this new chapter in the story of Swift. " +
    "After Apple unveiled the Swift programming language, it quickly became one of " +
    "the fastest growing languages in history. Swift makes it easy to write software " +
    "that is incredibly fast and safe by design. Now that Swift is open source, you can " +
    "help make the best general purpose programming language available everywhere."

使用 tuple

tuple 是 Swift 引入的一種新的數據類型,它可以方便支持方法的多返回值:

let numbersTuple = (1, 100, 1000)
    print("min: \(numbersTuple.0), max: \(numbersTuple.1), sum: \(numbersTuple.2)")

let numbersNamedTuple = (min: 1, max: 100, sum: 1000)
    print("min: \(numbersNamedTuple.0), max: \(numbersNamedTuple.1), sum: \(numbersNamedTuple.2)")
    print("min: \(numbersNamedTuple.min), max: \(numbersNamedTuple.max), sum: \(numbersNamedTuple.sum)")

Collections

創建集合:

Swift 的集合類型主要還是 Array 和 Dictionary :

var fruits = ["apple", "banana", "oranage"]
var fruitsPrice = [
    "apple": 4.25,
    "banana": 6.2
]
print(fruitsPrice[fruits[1]]) // 6.2

定義空集合:

var emptyArray = [String]()
var emptyDictionary = [String: Float]()

將已有集合設置為空時,可以用如下簡寫:

fruits = []
fruitsPrice = [:]

使用 for in 遍歷集合:

for score in [1,2,3,4,5,6] {
    print(score * score * score)
}

for (key, val) in ["one": 1, "two": 2] {
    print("\(val) is \(key)")
}

if else 和 Optional

Swift 中新增一種類型 Optional,這個概念來自 Scala。 Optional 類似一個包裝器,它可以包裝一個數值,但是 Optional 可能返回 nil ,可能返回數據。多用于錯誤處理,通常跟 if else 連用:

聲明 Optional:

var optionalString: String? = nil
//print(optionalString!) // nil 取值會報錯
print(optionalString == nil)

var optionalName: String? = "Jian"
print(optionalName!)

String? 表示一個 String 類型的 Optional。只有 Optional 可以接受 nil 值。如果對一個 nil 的 Optional 取值會報錯,一般取值前會對 Optional 做判斷:

var optionalString: String? = nil

if optionalString != nil {
    let val = optionalString!
} else {
    print("There is no value")
}

if-else 簡化 Optional 取值:

Swift 為上面這種方式提供一種簡寫:

if let val = optionalString {
    print("There is a value: \(val)")
} else {
    print("There is no value")
}

通常會將 if-else 和 Optional 這么使用:

var optionalName: String? = "Jian"
print(optionalName!)

var greeting = "Hello!"

if let name = optionalName {
    greeting = "Hello \(name)"
}

Optional 默認值:

使用 ?? 可以為 Optional 提供默認值:

let fullName: String = "Jian"
let nickName: String? = nil
let displayName = "\(nickName ?? fullName)"

switch

Swift 中的 switch 強大很多,支持 String,多值匹配,條件匹配:

let vegetable = "red pepper"

switch vegetable {
case "celery":
    print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
    print("Taht would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?") // Is it a spicy red pepper?
default:
    print("Everythink tasts good")
}

使用循環

for in 循環

Swift 中的 for in 和 javascript 中的有點類似。使用 for in 便利 Dictionary:

let numbersDict = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25]
]

var largest = 0

for (kind, numbers) in numbersDict {
    for number in numbers {
        number
        if number > largest {
            largest = number
        }
    }
}
print(largest) // 25

使用 for in 遍歷 Range:

var total = 0
for i in 0..<4 {
    total += i
}
print(total) // 6

while 循環

一般語言都會提供 while 和 do {} while 循環。Swift 采用 while 和 repeat {} while :

var n = 1
while n < 100 {
    n += n
}
print(n) //128

var m = 1
repeat {
    m += m
} while m < 100
print(m) // 128

Functions

Swift 中的函數具有 javascript 和 objective c 的雙重特征。并且函數在 Swift 中是一等公民(First-class type),具有高階函數的特性。

定義函數

一般情況下,跟 Objective C 方法一樣,需要給函數參數提供 Label:

func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet(person: "Jian", day: "Friday")

使用 _ 表示省略 Label:

func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet("Jian", on: "Friday")

函數可以使用 tuple 返回多個值:

func calcStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0

    for score in scores {
        if score > max {
            max = score
        } else if score < min {
            min = score
        }

        sum += score
    }

    return (min, max, sum)
}

let statistics = calcStatistics(scores: [5, 1, 100, 30, 90])
print(statistics.sum) // 226
print(statistics.2)   // 226

無限參數:

func sumOf(numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}
sumOf()                             // 0
sumOf(numbers: 1, 2, 3, 4, 10)      // 20

使用 Int... 在函數的最后一個參數,表示后面可以接受無限個整數參數。

函數嵌套

func returnFifteen() -> Int {
    var y = 10
    func add() { y += 5 }
    add()
    return y
}
returnFifteen() // 15

高階函數

高階函數( high-order function ),是函數是編程的一個概念,高階函數的特點:

  • 可以將函數當做返回值,即:可以使用函數創建函數
  • 可以將函數當做參數接收

使用函數創建另一個函數:

func createIncrementer() -> ((Int) -> Int) {
    func plusOne(number: Int) -> Int {
        return 1 + number
    }

    return plusOne
}
let incrementer = createIncrementer()
incrementer(10)

函數作為參數:

func hasAnyMatches(_ list: [Int], matcher: (Int) -> Bool) -> Bool {
    for item in list {
        if matcher(item) {
            return true
        }
    }

    return false
}

func lessThanThen(number: Int) -> Bool {
    return number < 10
}

hasAnyMatches([20, 10, 7, 12], matcher: lessThanThen)

Closure (閉包)

Closure 可以理解匿名函數,在很多 Callback 和集合操作中使用:

hasAnyMatches([20, 10, 7, 12]) { (item: Int) -> Bool in
    item < 10
}
[20, 10, 7, 12].map { (item: Int) -> Int in
    return 3 * item
}
[20, 10, 7, 12].map({ item in 3 * item })

如果省略 () 后, Closure 是唯一的參數:

let sortedNumbers = [20, 10, 7, 12].sorted { $0 > $1 }
print(sortedNumbers)

Objects and Classes

定義和使用類:

class Shape {
    var numberOfSides = 0

    func simpleDescription() -> String {
        return "A shap with \(numberOfSides) sides."
    }
}
let shape = Shape()
shape.numberOfSides = 10
shape.simpleDescription()

使用繼承:

class NamedShape : Shape {
    var name: String

    init(name: String) {
        self.name = name
    }
}

// inherit and override
class Square: NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)"
    }
}

let square = Square(sideLength: 10.0, name: "Jian's Square")
square.area()
square.simpleDescription()

使用屬性

Swift 中對屬性的處理,有些像 C#。

使用 getter/setter

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }

    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)"
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "A triangle")
print(triangle.perimeter)           // 9.3

triangle.perimeter = 9.9
print(triangle.sideLength)          // 3.3

使用 willSet:

class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        willSet {
            square.sideLength = newValue.sideLength
        }
    }

    var square: Square {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }

    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}

var triangleAndSquare = TriangleAndSquare(size: 10, name: "other shape")
print(triangleAndSquare.square.sideLength)          // 10.0
print(triangleAndSquare.triangle.sideLength)        // 10.0

triangleAndSquare.square = Square(sideLength: 50, name: "Large square")
print(triangleAndSquare.triangle.sideLength)        // 50.0

使用 willSet 保證 square 和 triangle 的 sideLength 始終相等。

使用 Optional 類型

使用 ?. 取值,當值為 nil 時返回 nil ,而不是報錯。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
let nilSquare: Square? = nil
let nilLength = nilSquare?.sideLength

Enumerations

定義 enum 類型:

enum Level: Int {
    case Zero, First, Second
}
Level.Zero.rawValue
Level.First.rawValue

enum 的 rawValue 默認從 0 開始,依次遞增。

在 enum 中創建方法:

enum Suit {
    case spades, hearts, diamonds, clubs
    func simpleDescription() -> String {
        switch self {
        case .spades:
            return "spades"
        case .hearts:
            return "hearts"
        case .diamonds:
            return "diamonds"
        case .clubs:
            return "clubs"
        }
    }
}

定義特性類型的 enum:

enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king

    func simpleDescription() -> String {
        switch self {
        case .ace:
            return "ace"
        case .jack:
            return "jack"
        case .queen:
            return "queen"
        case .king:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}
let ace = Rank.ace                      // ace
let aceRawValue = ace.rawValue          // 1

enum Rank: Int 設置 enum 的 rawValue 為 Int 。我們也可以通過 rawValue 來創建 enum :

if let convertedRank = Rank(rawValue: 3) {
    let threeDescription = convertedRank.simpleDescription()        // 3
}

復雜的 enum :

enum ServerResponse {
    case result(String, String)
    case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:00 pm")
let failure = ServerResponse.failure("Out of cheese")

switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset)") // Sunrise is at 6:00 am and sunset is at 8:00 pm
case let .failure(message):
    print("Failure ... \(message)")
}

Structs

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescript() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .three, suit: .spades)   // Card
print(threeOfSpades.simpleDescript())                   // The 3 of spades

struct 和 class 最重要的區別是:

  • struct 傳遞值,始終傳遞 copy
  • class 傳遞引用。

Protocol

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

Protocol 與 Java 中的 Interface 概念類似。在 Swift 中,class、struct、enum、extension 都可以實現 Protocol:

class 實現 protocol:

class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A simple class."
    var moreProperty: Int = 315
    func adjust() {
        simpleDescription += " Now 100% adjusted"
    }
}
var simpleClass = SimpleClass()
simpleClass.adjust()
print(simpleClass.simpleDescription)        // A simple class. Now 100% adjusted

struct 實現 protocol:

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted) "
    }
}

var simpleStruct = SimpleStructure()
simpleStruct.adjust()
print(simpleStruct.simpleDescription)

mutating 修飾符表示,當前方法在 struct 中可以修改 struct 的值。

在 protocol 的應用中,可以使用 Java 中面向 Interface 編程:

let protocolValue: ExampleProtocol = simpleStruct
print(protocolValue.simpleDescription)              // A simple structure (adjusted)

Extensions

Swift 中的 extension 和 ruby 中的 Open Class 概念很像,在 ObjC 中是 Category 。它可以為已有類型添加新的特性:

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }

    mutating func adjust() {
        self += 10
    }
}

print(7.simpleDescription)

Error Handling

throws 異常

enum PointerError: Error {
    case outOfPaper
    case noToner
    case onFire
}

// throw error
func send(job: Int, toPointer printerName: String) throws -> String {
    if printerName == "Never has toner" {
        throw PointerError.noToner
    }
    return "Job sent"
}

catch 和處理異常

對于具有 throws 聲明的方法,需要使用 try 關鍵字調用,然后使用 do {} catch {} 包裹:

do {
    let pointerResp = try send(job: 1024, toPointer: "Never has toner")
    print(pointerResp)
} catch { // catch all errors
    print(error) // use error by default
}

處理多個異常:

do {
    let pointerResponse = try send(job: 1024, toPointer: "Jian")
    print(pointerResponse)
    throw PointerError.onFire

} catch PointerError.onFire {
    print("I'll just put shi over here, with the result of the fire.")      // I'll just put shi over here, with the result of the fire.
} catch let pointerError as PointerError {
    print("Printer error: \(pointerError) .")
} catch {
    print(error)
}

通常 catch 多個 Error 時, catch 順序需要從小異常,到范圍更大的異常。

使用 try?

// try? -> Optional
let pointerFailure = try? send(job: 1024, toPointer: "Never has toner")         // nil
let pointerSuccess = try? send(job: 2048, toPointer: "Good pointer")        // Job sent

使用 defer

在方法 throws 時,會終端當前函數后續的代碼執行,使用 defer 可以確保 defer 代碼段中的代碼在函數返回前始終被執行。這個概念有些像 Java 的 try {} catch {} finally {} 中的 finally :

func ensureExecute() throws -> String {
    defer {
        print("Complete")
    }

    do {
        try send(job: 1024, toPointer: "Never has toner")
    } catch {
        throw error
    }

    return "Executed"
}
let executed = try? ensureExecute()     // Complete

Generic

Swift 開始支持泛型(Generic):

enum OptionalValue<Wrapped> {
    case none
    case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none     // none
possibleInteger = .some(100)                        // some(100)

使用 where 限定泛型的類型:

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
    where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element {

        for lhsItem in lhs {
            for rhsItem in rhs {
                if lhsItem == rhsItem {
                    return true
                }
            }
        }

        return false
}
anyCommonElements([1,2,3,4,5], [5])

where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element 限制 T 和 U 中的元素,必須實現 Equatable ,并且 T 和 U 中的元素是同一種類型。

 

 

來自:http://www.jianshu.com/p/3d8963cdb0b9

 

 本文由用戶 PauKohn 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!