Apple的WWDC在昨天圓滿結束,期望iPhone6的同學可能很失望,但是對於程式設計師們,他們又多了好多新玩具。除了成堆的新API,Apple還發布了一款全新的程式語言——Swift。
早就有謠言Apple會想辦法替換掉ObjectiveC,但大家都沒當回事。可這次,Apple直接放了大招。
並不是Apple喜歡折騰,是ObjectiveC的確不招人喜歡:
- 作為一個C語言的變種,它有較為陡峭的學習曲線
- 缺乏動態特性。雖然新版的ObjectiveC已經非常努力的更新很多看起來很NB的東西,但是這在其他語言確實天生支援的。
- Java直到8才支援lamda,但ObjectiveC的2013年就支援Block了。不過Block的限制太多,而且語法醜陋
- id和instancetype這些東西的產生都是很無奈的,沒法徹底解放複雜的型別申明
- 說好的generic和auto-boxing呢
- …
- [[ObjectievC 的語法] 太羅嗦]
- …(歡迎補充)
Swift釋出後,我第一時間下載了免費的教程,看完了Language Guide後寫下我第一篇關於Swift的文章。
可以預料,網上已經有很多文章在說Swift又如何如何的好了。它到底好不好,我們這打個問號。先讓說說它十分有特色的地方,順便附上免費吐槽。
Swift的產生
Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility.
我們解讀下Swift程式設計指南中開篇的第一句話:
- 它是為了編寫iOS和OSX的應用而產生的
- 它吸取了C和ObjectiveC的優點
- 它去掉了為了實現對C相容性而做出的妥協
Swift的產生是面向未來的,並且是冷靜分析了當前Apple軟體生態圈之後歸納總結出新語言。程式設計指南的開篇也提到,Apple內部已經使用了Swift多年。
事實上,有LLVM在前,大家應該不難想像Apple可以搞出很多種高階語言出來,反正只要能通過LLVM編譯,就能接入Apple的生態體系了。看看隔壁的微軟吧,一個.net上面有多少種語言?
Swift也不是Apple的第一次折騰。從Carbon到Cocoa,從MRC到ARC,大家都是含著淚走過來的。其實,Swift也並不能宣判ObjectiveC的死刑,我相信,對於這種翻天覆地的改動,就算一切順利,也需要一年左右的時間讓開發者接受。Apple很可能會觀察社群動向,同時對兩種語言進行調整,最壞的情況下,有一部分市場的應用仍舊使用ObjectiveC,而另外一部分,尤其是遊戲,很可能徹底拋棄ObjectiveC,而使用更敏捷的Swift。
Swift的定位,意味著它有豐富的動態特性,同時擁有靜態語言的效能和安全性。你可以通過XCode6的Playground專案進行實驗,也可以直接通過Swift編譯器進行除錯。Swift Compiler位於:
/Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift
變數和資料型別
let it be
Swift的所有變數都需要用let或者var宣告。這兩個關鍵字的在別的語言廣泛存在:ECMAScript(JavaScript、ActionScript)、Go。Swift也並不要求開發者一定需要寫明其資料型別,因為編譯器有一定能力推斷變數的資料型別。
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
注意,這並不是說Swift變成弱型別了。事實上,Swift的變數一旦確定了型別,便不能改變。而且,Swift也不存在隱式轉換。例如,如果需要字串拼接,需要你手動轉換:
let widthLabel = label + String(width)
Generics
let emptyDictionary = Dictionary<String, Float>()
ObjectiveC的資料結構最大的詬病就是不支援Generic了。Swift還提供了兩個萬精油的資料型別:
- AnyObject
- Any
相當於於void*
和id
了,這些東西聯合起來可以說是讓大家對資料結構的應用更靈活一些了。
資料型別
除了常見的Int、UInt、Float、Double、Bool之外,它還有目前動態語言喜歡使用的Tuple。
var my2dPosition = (20, 20)
var my3dPosition = (20, 10, 50)
這也意味著,支援返回多個數值和Deconstructing了。
var (a,b) = (10,20)
然後就是Range
,一種全閉合,一種半開半閉。
- 1…3
- 1..3
函式
好吧,Swift函式也很難看。它看起來像是Go、Ruby的結合體。但從特性上來講,Swift的函式是非常優秀的。
- Functions are a first-class type
- 可變的函式列表
- Closure
- 尾部Closure呼叫
- 捕獲當前作用域
- Local and external argument names
這部分將開來講太複雜了。可以說該有的動態語言特性都有了。
流程控制
更嚴格的if語句在判斷條件時,並不考慮0,而只考慮Boolean。
功能無比強大的switch再也不是雞肋了:
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
println("(0, 0) is at the origin")
case (_, 0):
println("((somePoint.0), 0) is on the x-axis")
case (0, _):
println("(0, (somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
println("((somePoint.0), (somePoint.1)) is inside the box")
default:
println("((somePoint.0), (somePoint.1)) is outside of the box")
}
// prints "(1, 1) is inside the box
enum、class、struct
把enum
放在這裡,是因為Swift裡面的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.toRaw())
}
}
}
面對如此凶殘的enum
我們怎麼把持的住?
Swift的類繼承可能時Swift裡最接近C、C++的地方了。無論是它的預設建構函式、解構函式,還是它後面提到的操作符過載都是C的那套思想,只是表現形式換了下。這意味著,這些東西很麻煩。
而同時又有動態語言常有的getter
和setter
那套。
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
每個Property還有兩個特殊的observer:
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
println("About to set totalSteps to (newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
println("Added (totalSteps - oldValue) steps")
}
}
}
}
其他的如Protocol
、Extension
什麼的依舊是有的,並且,兩者都可以當做Type作為宣告變數。
Optional Type
還不知道這個東西該怎麼翻譯成中文,直接上程式碼吧:
if let johnsStreet = john.residence?.address?.street {
println("John`s street name is (johnsStreet).")
} else {
println("Unable to retrieve the address.")
}
// prints "Unable to retrieve the address."
一個值要麼存在,要麼為nil。和if一起使用被成為Optional Binding
。
這恐怕是Swift裡最晦澀的概念了。由於Swift裡沒有指標,而ObjectiveC裡一個預設行為就是向nil
物件的呼叫(傳送訊息)是沒有任何效果,這個特點要完整遷移到Swift裡是很困難的。Optional Type的確提供了這個可能, 但這也恐怕是Swift學習成本最大的地方了。
與Cocoa和CocoaTouch的混用
Swift可以和Cocoa、CocoaTouch進行檔案級別的混用,也就是說你的專案裡可以同時存在這兩種檔案。在Swift裡使用Cocoa的API也是可以的:
let dataViewController = storyboard.instantiateViewControllerWithIdentifier("DataViewController") as DataViewController
Apple通過了複雜的橋接實現了這些,但可以遠見之後會有很第三方多框架相容性問題了。
Swift已經不支援C和C++程式碼的混用了,要記住這是Swift產生的初衷之一。
期望和展望
個人預測它的流行程度很快會超過Go、Ruby,並與Python並排,之後會穩定上升,最終是否會超過ObjectiveC,甚至接近Java,都需要看Apple的佈局了。
XCode6內目前是支援以兩種不同的語言來編寫應用的,但不知道未來是否會慢慢淘汰ObjectiveC。Apple完全有能力維護兩套語言,問題在於它是否需要。在很多領域,開發者早就渴望一種充滿動態語言特性的開發語言了,想想iOS上那些內嵌Lua的應用吧。
但是,我覺得Swift並不該像它的前輩那樣停留在編寫幾個iOS或者Mac應用上面,它應該走出來,成為真正意義上的通用語言。