淺談Swift編程語言

jopen 10年前發布 | 34K 次閱讀 Swift Apple Swift開發

在過去的幾年中,移動應用程序風靡全世界并且已經改變了我們使用互聯網進行工作或者休閑的方式。為了創建移動應用程序,各種技術應運而生,同時開發 過程也開始將其作為一等公民來對待。盡管移動似乎已經無處不在了,但是它的未來才剛剛開始。我們正面對著新一代的移動設備,例如可穿戴設備以及組成物聯網 的大量移動工具。我們將會面對新的用來展示數據和接受命令的用戶界面。同時,我們將會看到越來越多的公司真正地實現移動優先。所有的這一切都將會影響我們 在未來的幾年中設計、開發和測試軟件的方式。

InfoQ的這篇文章是快速變化的移動技術世界中一系列文章的一部分。你可以通過這里訂閱這一系列,屆時如果有新文章發布那么會通知你。

蘋果公司最近推出了Swift 1.0——一門針對iOS和OSX開發的新編程語言。不要將蘋果的Swift與老的并行腳本語言混淆。Swift的目標是讓iOS和OSX開發變得更簡單,更有樂趣。在本文中,我將會解釋我認為Swift所具有的最具殺傷力的5個特性以及我為什么會這樣認為的原因,雖然這些特性現在依然出于測試階段,但是卻值得我們一試。

蘋果已經擁有了一門編程語言——Objective-C。那么為什么還要引入另一門編程語言呢?這是因為雖然Objective-C在被創建的時候 可能已經非常地獨特,同時也很先進,但是它現在并沒有當今語言的味道。例如,在消費者方面像Ruby這樣的腳本語言已經被廣泛采用,這很大程度上得益于它 干凈的語法。在企業領域,具有類型推理能力的強類型(類型安全的)語言更受歡迎,為了將函數式編程語言所具有的函數即對象、Lambda表達式等經典特性 引入進來,C#和Java(或者Scala)等語言都做出了大量的努力。Objective-C一直都缺少這類東西,例如干凈的語法(和語法糖),類型推 理。而Swift正是為了填補這個空白。

這并不是說Objective-C并不是一門優秀的編程語言。實際上,它是一門優秀的語言。但是我確實看到有足夠的空間可以成功地替代Objective-C。進一步講,同時也要感謝Swift的優秀,我認為Swift一定會像野火那樣迅速蔓延開來。

現在,就讓我們看看Swift都提供了什么吧。從語言的角度看,Swift是非常了不起的。蘋果借鑒了Scala和C#這些現代語言的優點,構建了 一門非常簡單,但是功能非常強大的語言。它非常完美地融合了面向對象和函數式編程范式——但是說Swift是一門函數式語言是一種極大的延伸。下面就讓我 們看看Swift最具殺傷力的5個特性。

#1: 語法糖

從語法上講Swift非常華麗。它是一門非常簡單、干凈的語言,同時可讀性也非常好,即使以現在的標準來衡量也是如此。你馬上就會發現在設計一門語 言的時候簡單性是一個關鍵要素。例如,大家所熟知的語句末尾的分號。蘋果決定將分號作為可選的,雖然這看起來相關性并不是非常強,但是它卻讓我們看到了蘋 果為了盡可能地保持語法干凈所做出的努力。

簡單性方面的其他例子包括字符串插入,以及語言對數組和循環處理的支持。

字符串插入

var message = “Hello World” “The message is \(message)” //The message is Hello world var a = 1, b = 2 “The sum is \(a + b)” //The sum is 3

循環

var length = 10
for i in 0..

數組

var list = ["a", "b"]
list += ["c", "d"]

以上僅是Swift為簡單性提供語言支持的一部分示例。需要注意的是你依然可以使用Array類的“append”方法連接數組,而蘋果之所以走了額外的一英里將其構建為語言的一部分目的是為了展示他們設計Swift的目標。

如果你想學習Swift并對一些這樣的示例代碼進行測試,那么可以嘗試下Xcode 6,它的代碼實時預覽 (Playground)功能太酷了,簡直無法用語言形容。實時預覽功能讓你能夠實時地隨著你的輸入對代碼進行測試。它會執行你在開發環境中輸入的所有內 容,提供與變量值、函數調用返回值以及特定代碼塊被執行的次數相關的詳細信息。打開Xcode 6中的實時預覽功能非常簡單:

(單擊放大圖片)

淺談Swift編程語言

下面的圖片展示了實時預覽功能:

(單擊放大圖片)

淺談Swift編程語言

#2: 函數是一等對象

越來越多的語言將函數作為一等公民并支持高級函數。例如,最近發布的Java 8引入了Lambda表達式。它的理念很簡單,就是讓函數可以接受函數類型的參數,同時也可以將函數作為返回值。理念的簡單性奠定了它強大的基礎,因為這 樣支持更多的抽象。例如,我們可以將一個“過濾(filter)”函數應用到一個數組,該過濾函數接受數組中的每一個條目作為參數,通過特定的標準對條目 進行判定從而完成對給定數組的過濾。使用更加通用的方法的關鍵是能夠接受函數類型的參數。下面就讓我們看看定義函數的語法。

Swift定義函數的語法與傳統的Haskell這樣的函數型語言相似,但并不完全一樣。箭頭(->)的左邊是參數以及參數的類型,右邊是返 回值類型。在本文的示例中,我們想要過濾一個數字列表,因而基于一個給定的數字我們會返回一個Bool類型。在這種情況下,函數看起來可能是這樣的:

(Item:Int) -> Bool

這段代碼的意思是接受一個Int類型的參數,返回一個Bool類型的值。很顯然,你可以包含多個參數,但是不太明顯的是,你還可以返回多個值,而這不需要創建一個容器對象。在后面的示例中,函數會返回一個元組 。

一個過濾整數的函數定義可能是這樣:

funct bigNumbersOnly (item:Int) -> Bool {
return item > 3
}

現在,我們已經創建了自己的過濾函數,下面讓我們看看可以接受函數參數類型的“filter”函數。

var numbers = [1, 2, 3, 4, 5]
var bigOnes = numbers.filter(bigNumbersOnly)

在這個示例中,filter是一個高階函數,因為它的參數類型是函數。在Swift中,函數也是對象,這意味著我們可以定義內聯函數:

var numbers = [1, 2, 3, 4, 5]
var bigOnes = numbers.filter({(item:Int) -> Bool in return item > 3})

或者我們也可以將函數賦值給某個變量,稍后再使用它:

//define two variables of type function
var biggies = {(item:Int) -> Bool in return item > 3 }
var threes = {(item:Int) -> Bool in return item == 3 }
//decide which one to apply at runtime
var result = numbers.filter(onlyThrees ? threes : biggies)

當今,將函數作為對象,讓用戶能夠像使用參數那樣引用、傳遞函數已經成為一種優美的標準。而Swift實現方式的簡潔性依然是一個值得稱道的地方,這一核心概念配合類型推理可以讓你事半功倍。

#3:強類型與類型推理

在企業開發領域,我們非常習慣于使用強類型(或者說類型安全的)語言。強類型語言通常會給我們帶來一點額外的自信,因為它能夠在編譯時進行錯誤檢查,如果這些語言也能夠支持類型推理那么將會是一種非常好的體驗。例如,可以這樣:

//Without Type inference
var x:String = "bar"
//With Type inference
var y = "bar"

注意,第二行的語句并沒有聲明變量的類型。因為Swift知道“bar”是一個字符串,所以我們并不需要顯式地定義它的類型,當然我們也可以指定,正如第一個語句那樣。這看起來好像并沒有特別大的作用,但是如果推理的是函數的類型那么它就會變得十分有趣。

那么如果不使用類型我們應該如何定義之前例子中的函數呢?下面的代碼展現了Swift的實現:

//$0 will map to the first parameter, $1 to the second...
var result = numbers.filter({ return $0 == 3})

沒有比這更簡潔的了!如果你的參數不止一個,同時想要通過名字引用參數,那么可以這樣做:

{a, b in return a > b }

#4 泛型

Swift提供的另一個非常便利的特性是泛型。在企業開發領域,泛型首先被引入到了C#中,在獲得了大量的關注之后Java也引入了該特性。使用泛 型可以讓開發者消除類型轉換,因為編譯器能夠運行特定的類型檢查,而對于不支持泛型的語言而言這是無法做到的。雖然剛開始將泛型引入C#的時候確實產生了 一些爭論,但是現在它已經被C#和Java社區所普遍接受。

泛型提供了一種方式可以讓我們推遲類型的定義,通常(但不限于)是參數和返回值的類型。雖然它聽起來很復雜,但是實際上通過一個簡單的示例我們就能非常容易地理解它。

//At the moment of creating this function
//I am not defining what T is. The actual
//Type of T will be deferred to the call
//of the doNothing function.
func doNothing (item:T) -> T {
   return item
}

//When I call doNothing, I am implicitly
//setting the type of T to the Type of the
//parameter I am sending. In this case,
//an Array.
//Notice how the compiler knows, that the
//return type is an Array.
doNothing([1, 2, 3]).count

雖然上面并不是一個真實的例子,但是通過它我們能夠看到在編譯時確定數組內部元素類型的便利。下面是一個更簡單的示例,注意編譯器是如何知道數組是包含字符串類型的:

var list = ["hello", "world"]
list[0].uppercaseString //HELLO

泛型的使用范圍并沒有被限定于參數,我們也可以定義泛型類、枚舉和結構。事實上,在前面的示例中,list的類型是Array

你可能會將Swift中的泛型與Objective-C中的協議類比,雖然它們的語法非常相似,但是概念是非常不同的。Objective-C并不 支持泛型。協議提供了一種方式去聲明一個確定的實現符合某個消息契約,但是契約必須預先指定。例如,使用協議你并不能強迫數組中的所有條目都是同一類型的 (無論是什么類型),但是使用泛型能夠做到。除了概念上的不同之外,Swift并不支持協議,就像Objective-C不支持泛型一樣。

#5 元組

元組是非常簡單的概念,你可以定義一個有序的值組。當你需要將多個值作為一個參數來回傳遞、或者被調用的函數需要返回多個值的時候元組會非常有用。元組并不需要我們為它的值定義任何類型,編譯時會完成所有的類型推理和類型檢查工作。定義元組的語法如下:

(1, "Two", ["Three"])

在上面的例子中,我們創建了一個帶有三個值的元組,第一個是一個整數,第二個是字符串,第三個是一個字符串類型的數組。乍一看這很像一個數組,但概念完全不同。你不能從一個元組中刪除或者向里追加元素,同時注意編譯器是如何知道每一個值的確切類型的:

淺談Swift編程語言

你可以通過元素在元組內部的位置引用它的值,正如圖片所提示的那樣;或者你也可以為每一個值指定一個名稱。如果一個函數需要返回幾個值,那么這是非常方便的,同時它也能讓我們避免定義那些特定于某個函數的類或者結構。下面讓我們看一個這樣的例子:

func info(items:[Int]) -> (avg:Int, min:Int, max:Int) {
   var sum = items.reduce(0, { $0 + $1 })
   var min = items.reduce(Int.max, { $0 > $1 ? $1 : $0})
   var max = items.reduce(Int.min, { $0 < $1 ? $1 : $0})
   return (sum / items.count, min, max)
}

var result = info([1, 2, 3, 4, 5, 6])
result.avg //3
result.min //1
result.max //6

元組提供了一種非常簡單的使用多個值的方法,讓我們省去了定義一個特定的類或者結構的額外工作。

還有更多

除了上面介紹的特性之外Swift還有很多其他的優秀特性值得我們一看,例如屬性觀察器、可選鏈接以及擴展。

我相信Swift具備快速成為一門流行的iOS和OSX編程語言所需要的所有必須條件,無論是在企業領域還是在消費者領域。強類型和類型推理特性將會讓它非常適合于企業開發,而它的簡單性和干凈的語法則會吸引那些從事消費者項目的開發人員。

 來源:InfoQ

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