1. 程式人生 > >一、Swift 語法概述

一、Swift 語法概述

  Swift是Apple最新推出的語言,用於編寫iOS和OS X程式,與C語言和Objective-C相容。本系列的文章中的一些例子,都來自於蘋果官方的GUIDE: The Swift Programming Language,有興趣的同學可以去蘋果的官網下載英文原版的iBook。

一、Hello world

  Swift中不需要main函式,也不需要用;分開每一行的語句,一個簡單的Hello world如下所示:

println("Hello, world")

二、賦值

  使用let來建立一個常量,使用var來建立一個變數,如下所示:

var myVariable = 42
myVariable = 50
let myConstant = 42

  如果初始值沒有提供足夠多的型別資訊,需要用冒號來定義變數型別:
let implicitInt = 72
let implicitDouble = 72.0
let explicitDouble : Double = 72

  如上所示,變數可以隱式定義型別,也可以用冒號來顯式定義型別。

  但是,變數在初始化之外,永遠都不會隱式轉換型別的。例如有變數:

let label = "number is "
let num = 5

  那麼,下面的語句是錯的:
let numLabel = label + num

  原因是字串不能與整型相加,那麼正確的寫法應該是:
let numLabel = label + String(num)

  有一種更簡單的方法來包含需要轉換的值,就是在雙引號中使用反斜槓\來獲取變數的字串型值:
let numLabel = "number is \(num)"

  可以用方括號[ ]來建立詞典和陣列:
var shoppingList = ["catfish", "water"]
shoppingList[1] = "bottle of water"
var occupations = [
    "Malcolm":  "Captain",
    "Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

  用初始化器建立一個空白的詞典或列表:
let emptyArray = [String]()
let emptyDictionary = Dictionary<String, Float>()

  當陣列或型別的值可以被推斷出來時,可以用[ ] 代表一個空白陣列,用[:]代表一個空白詞典。

三、流程控制

1、if、switch case條件控制

  if、switch中的條件不需要括號,且switch語句中的case不需要加break,因為case中的語句不會跳轉到下一個case中。例如:

let hello = "hello"
switch hello {
case "hello":
    let lang = "English"
case "你好":
    let lang = "Chinese"
default:
    let lang = "other"
}

let score = 62
if score >= 60 {
    let result = "Passed"
} else {
    let result = "No pass"
}

  if語句中的條件一定要為布林值,而不是像C語言那樣傳入0和非0即可。

2、for、for-in、while、do while迴圈控制

  迴圈語句中的條件同樣無需新增括號。當在for-in語句中使用一對值時,可以對辭典的鍵、值進行迭代,例如下面是一個返回辭典中最大值的程式碼:

let interestingNumbers = [
    "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 interestingNumbers{
    for number in numbers{
        if number > largest {
            largest = number
        }
    }
}
largest

  可以在for語句中用..<來簡化程式碼的編寫,以下是兩段等效的程式碼:
for i in 0..<4{ }
for var i=0; i < 4; ++i { }

四、函式和閉包

  使用func定義一個函式,用 -> 表示函式的返回型別,類似於C++11中的函式返回型別後置。函式形參與型別直接用冒號隔開,形參與形參之間用逗號隔開。

func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
}
greet ("Froser", "Sunday")

  可以使用元組(Tuple)來使函式返回多個值:
func getNumber() -> (Double, Double) {
    return (1.0, 2.0)
}

  可以使用...來接收不定長引數,這些不定長引數將作為一個列表:

func sumOf(numbers: Int...) -> Int {
    var sum = 0;
    for number in numbers {
        sum += number
    }
}
sumOf()
sumOf(1,3,100)

  函式可以被巢狀,被巢狀的函式可以訪問外部函式的變數:
func test() -> Int {
    var x = 10
    func add(){
        x += 5
    }
    add()
    return x
}

  函式也是一種型別,例如,我們可以讓一個函式返回另外一個函式並呼叫它。
func makeIncrement() -> (Int -> Int) {
    func increase(number: Int) -> Int {
        return number + 1
    }
    return increase
}

  如上所示,makeIncrement返回一個接受一個引數為Int,返回值為Int的函式。在C++中,如果要返回函式,一般是返回函式的地址,在C#中,我們可以把內部的巢狀函式作為一個Lambda表示式來返回,也可以返回一個函式的委託。

  同理,函式的形參也可以為函式:

func equals (numberA: Int, numberB: Int, equals: (Int, Int) -> Bool ) -> Bool {
    return equals(numberA, numberB)
}

  Swift支援匿名函式,你可以把匿名函式看成一個變數,只不過它可以被呼叫而已。匿名函式不能包含函式名,且要用in來分開函式簽名和函式體:
object.save({
    (number: Int) -> Int in
    let result = 3 * number
    return result
    })

五、類與物件

  使用class關鍵字來建立一個類,類內部可以新增變數、常量和方法(Method)

class Shape{
    var numberOfSides = 0
    func description() -> String {
        return "A shape with \(numbeOfSides) sides."
    }
}

  如同一般的面向物件程式設計,用“.”訪問物件中的成員。

var shape = Shape()
shape.numberOfSides = 7

  使用init方法來為類建立一個構造器,用deinit為類建立一個析構器。

  就像C++、C#那樣,通過在類名稱後面加冒號可以表示類的繼承。如果子類要覆蓋一個基類方法,必須要加上關鍵字override。意外地覆蓋了基類方法卻沒有加override會導致編譯器報錯。

class A{
    func test(){}
}
class B : A{
    override func test(){}
}

  可以像C#那樣,在類中定義屬性,並編寫它們的get和set方法:
class A{
    var _property : String = ""
    var property : String{
        get{
            return "hello " + _property
        }
        set{
            _property = newValue
        }
    }
}

  在為property賦值時,會呼叫set方法,取值時會呼叫get方法。set方法中的newValue表示property被賦予的值。

  除此之外,Swift還定義了兩種屬性方法:willSet和didSet,分別代表屬性賦值前和賦值後執行的方法。

  Swift中,類中的func被稱為“方法(Method)”,方法可以訪問類成員中的值:

class Counter {
    var count: Int = 0
    func add() {
        count++
    }
}

六、列舉

  使用enum關鍵字建立一個列舉型別,並用case定義它的列舉值。列舉型別可以看成是一個類,因為它可以包含自己的方法,當呼叫自身方法時,一個使用self獲取自身的資訊:

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four
    func description() -> String {
        switch self {
            case .Ace:
                return "ace"
            default:
                return String(self.toRaw())
        }
    }
}

  如上所示,我們定義了列舉型別Rank,併為它定義了其原始型別為Int。如果原始型別不重要,你也可以不提供,即去掉“: Int”,此時你亦不可為列舉成員賦予初值。

  當編譯器能夠推斷出列舉物件的型別時,不必在賦值時加上列舉型別名,如可以將Rank.Ace簡化為.Ace。

  列舉成員甚至可以帶引數:

enum ServerResponse{
    case Success(String)
    case Error(String)
}

let error = ServerResponse.Error("Password incorrect!")

七、結構

  使用關鍵字struct建立一個結構,與“類”不同的是,結構在傳遞時,是按照值傳遞的,而拷貝則是按照“引用”來傳遞的。請參考C#、Java中的值傳遞、引用傳遞。

八、協議

  協議如同C#、Java中的“介面(Interface)”:

protocol Example{
    var description: String { get }
    mutating func adjust()
}

  繼承了此協議的類、結構,都必須實現description屬性的get方法,以及adjust方法。

  在結構中,實現adjust方法必須在前面新增關鍵字mutating,表示它會改變自身內部成員的值,而class本身就可以改變自身成員的值,就不必添加了:

class ClassWithDescription : Example {
    var description: String= "very simple"
    func adjust(){
        description=""
    }
}

struct StructWithDescription : Example {
    var description: String= "very simple"
    mutating func adjust(){
        description=""
    }
}

  如同面向物件設計那樣,可以用Example型別來定義任何繼承了Example協議的物件,但是它只會包含Example協議中的細節。

九、擴充套件

  如同C#中的擴充套件方法、Objective-C中的類別,使用extension關鍵字到一個已知型別,我們可以為這種型別新增擴充套件的屬性、方法。

extension Int: Example{
    ....
}

extension Int{
    ....
}

十、泛型

  Swift中有泛型函式、泛型方法、泛型結構、泛型列舉、泛型結構等。泛型的型別寫在尖括號<>中:

func repeat<ItemType>(item: ItemType, times: Int) -> [ItemType] {
    var result = [ItemType]()
    for i in 0..<times{
        result += item
    }
    return result
}
repeat ("knock", 4)

  可以在尖括號中加入where來約束泛型:
func test<T where T: Sequence> (arg: T){
    ....
}

十一、總結

  以上是列舉了一些Swift的語法點,可見Swift吸取了很多語言的成功經驗:如Javascript的動態與隨意性、C#的屬性機制、泛型機制、Java的列舉機制、C++11的後置型別返回,以及簡化了for迴圈的一些寫法(這個可能是和Perl學的),讓它能成為一門真正的面向物件動態型語言。

  之後,我會將Swift語言中的每一個細節都整理出來,希望能和大家一起學習。