這篇文章簡要介紹了蘋果于WWDC 2014發(fā)布的編程語言Swift。 原文作者: Lucida Blog 新浪微博 豆瓣 前言 在這里我認(rèn)為有必要提一下Brec Victor的Inventing on Principle,Swift編程環(huán)境的大部分概念都源自于Brec這個演講。 接下來進(jìn)入正題。 Swi
“ ”
閱讀器
蘋果Swift
這篇文章簡要介紹了蘋果于WWDC 2014發(fā)布的編程語言——Swift。 原文作者: Lucida Blog 新浪微博 豆瓣
前言 在這里我認(rèn)為有必要提一下Brec Victor的Inventing on Principle,Swift編程環(huán)境的大部分概念都源自于Brec這個演講。 接下來進(jìn)入正題。
Swift是什么? Swift是蘋果于WWDC 2014發(fā)布的編程語言,這里引用The Swift Programming Language的原話:
? 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 adopts safe programming patterns and adds modern features to make programming easier, more flexible and more fun. Swift’s clean slate, backed by the mature and much-loved Cocoa and Cocoa Touch frameworks, is an opportunity to imagine how software development works. Swift is the first industrial-quality systems programming language that is as expressive and enjoyable as a scripting language.
簡單的說: Swift用來寫iOS和OS X程序。(估計也不會支持其它屌絲系統(tǒng)) Swift吸取了C和Objective-C的優(yōu)點,且更加強(qiáng)大易用。 Swift可以使用現(xiàn)有的Cocoa和Cocoa Touch框架。 Swift兼具編譯語言的高性能(Performance)和腳本語言的交互性(Interactive)。
Swift語言概覽 基本概念 注:這一節(jié)的代碼源自The Swift Programming Language中的A Swift Tour。
Hello, world 類似于腳本語言,下面的代碼即是一個完整的Swift程序。
println( "Hello,?world" )? 變量與常量 Swift使用var聲明變量,let聲明常量。
var ?myVariable?=?42? myVariable?=?50? let?myConstant?=?42? 類型推導(dǎo) Swift支持類型推導(dǎo)(Type Inference),所以上面的代碼不需指定類型,如果需要指定類型:
let?explicitDouble?:?Double?=?70? Swift不支持隱式類型轉(zhuǎn)換(Implicitly casting),所以下面的代碼需要顯式類型轉(zhuǎn)換(Explicitly casting):
let?label?=? "The?width?is?" ? let?width?=?94? let?width?=?label?+?String(width)? 字符串格式化 Swift使用\(item)的形式進(jìn)行字符串格式化:
let?apples?=?3? let?oranges?=?5? let?appleSummary?=?"I?have?\(apples)?apples." ? let?appleSummary?=?"I?have?\(apples?+?oranges)?pieces?of?fruit." ? 數(shù)組和字典 Swift使用[]操作符聲明數(shù)組(array)和字典(dictionary):
var ?shoppingList?=?[ "catfish" ,? "water" ,? "tulips" ,? "blue?paint" ]? shoppingList[1]?=?"bottle?of?water" ? ?? var ?occupations?=?[? ????"Malcolm" :? "Captain" ,? ????"Kaylee" :? "Mechanic" ,? ]? occupations["Jayne" ]?=? "Public?Relations" ? 一般使用初始化器(initializer)語法創(chuàng)建空數(shù)組和空字典:
let?emptyArray?=?String[]()? let?emptyDictionary?=?Dictionary<String,?Float>()? 如果類型信息已知,則可以使用[]聲明空數(shù)組,使用[:]聲明空字典。
控制流 概覽 Swift的條件語句包含if和switch,循環(huán)語句包含for-in、for、while和do-while,循環(huán)/判斷條件不需要括號,但循環(huán)/判斷體(body)必需括號:
let?individualScores?=?[75,?43,?103,?87,?12]? var ?teamScore?=?0? for ?score? in ?individualScores?{? ????if ?score?>?50?{? ????????teamScore?+=?3? ????}?else ?{? ????????teamScore?+=?1? ????}? }? 可空類型 結(jié)合if和let,可以方便的處理可空變量(nullable variable)。對于空值,需要在類型聲明后添加?顯式標(biāo)明該類型可空。
var ?optionalString:?String??=? "Hello" ? optionalString?==?nil? ?? var ?optionalName:?String??=? "John?Appleseed" ? var ?gretting?=? "Hello!" ? if ?let?name?=?optionalName?{? ????gretting?=?"Hello,?\(name)" ? }? 靈活的switch Swift中的switch支持各種各樣的比較操作:
let?vegetable?=? "red?pepper" ? switch ?vegetable?{? case ? "celery" :? ????let?vegetableComment?=?"Add?some?raisins?and?make?ants?on?a?log." ? case ? "cucumber" ,? "watercress" :? ????let?vegetableComment?=?"That?would?make?a?good?tea?sandwich." ? case ?let?x?where?x.hasSuffix( "pepper" ):? ????let?vegetableComment?=?"Is?it?a?spicy?\(x)?" ? default :? ????let?vegetableComment?=?"Everything?tastes?good?in?soup." ? }? 其它循環(huán) for-in除了遍歷數(shù)組也可以用來遍歷字典:
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? while循環(huán)和do-while循環(huán):
var ?n?=?2? while ?n?<?100?{? ????n?=?n?*?2? }? n? ?? var ?m?=?2? do ?{? ????m?=?m?*?2? }?while ?m?<?100? m? Swift支持傳統(tǒng)的for循環(huán),此外也可以通過結(jié)合..(生成一個區(qū)間)和for-in實現(xiàn)同樣的邏輯。
var ?firstForLoop?=?0? for ?i? in ?0..3?{? ????firstForLoop?+=?i? }? firstForLoop? ?? var ?secondForLoop?=?0? for ? var ?i?=?0;?i?<?3;?++i?{? ????secondForLoop?+=?1? }? secondForLoop? 注意:Swift除了..還有...:..生成前閉后開的區(qū)間,而...生成前閉后閉的區(qū)間。
函數(shù)和閉包 函數(shù) Swift使用func關(guān)鍵字聲明函數(shù):
func?greet(name:?String,?day:?String)?->?String?{? ????return ? "Hello?\(name),?today?is?\(day)." ? }? greet("Bob" ,? "Tuesday" )? 通過元組(Tuple)返回多個值:
func?getGasPrices()?->?(Double,?Double,?Double)?{? ????return ?(3.59,?3.69,?3.79)? }? getGasPrices()? 支持帶有變長參數(shù)的函數(shù):
func?sumOf(numbers:?Int...)?->?Int?{? ????var ?sum?=?0? ????for ?number? in ?numbers?{? ????????sum?+=?number? ????}? ????return ?sum? }? sumOf()? sumOf(42,?597,?12)? 函數(shù)也可以嵌套函數(shù):
func?returnFifteen()?->?Int?{? ????var ?y?=?10? ????func?add()?{? ????????y?+=?5? ????}? ????add()? ????return ?y? }? returnFifteen()? 作為頭等對象,函數(shù)既可以作為返回值,也可以作為參數(shù)傳遞:
func?makeIncrementer()?->?(Int?->?Int)?{? ????func?addOne(number:?Int)?->?Int?{? ????????return ?1?+?number? ????}? ????return ?addOne? }? var ?increment?=?makeIncrementer()? increment(7)? func?hasAnyMatches(list:?Int[],?condition:?Int?->?Bool)?->?Bool?{? ????for ?item? in ?list?{? ????????if ?condition(item)?{? ????????????return ? true ? ????????}? ????}? ????return ? false ? }? func?lessThanTen(number:?Int)?->?Bool?{? ????return ?number?<?10? }? var ?numbers?=?[20,?19,?7,?12]? hasAnyMatches(numbers,?lessThanTen)? 閉包 本質(zhì)來說,函數(shù)是特殊的閉包,Swift中可以利用{}聲明匿名閉包:
numbers.map({? ????(number:?Int)?->?Int?in ? ????let?result?=?3?*?number? ????return ?result? ????})? 當(dāng)閉包的類型已知時,可以使用下面的簡化寫法:
numbers.map({?number? in ?3?*?number?})? 此外還可以通過參數(shù)的位置來使用參數(shù),當(dāng)函數(shù)最后一個參數(shù)是閉包時,可以使用下面的語法:
sort([1,?5,?3,?12,?2])?{?$0?>?$1?}? 類和對象 創(chuàng)建和使用類 Swift使用class創(chuàng)建一個類,類可以包含字段和方法:
class ?Shape?{? ????var ?numberOfSides?=?0? ????func?simpleDescription()?->?String?{? ????????return ? "A?shape?with?\(numberOfSides)?sides." ? ????}? }? 創(chuàng)建Shape類的實例,并調(diào)用其字段和方法。
var ?shape?=?Shape()? shape.numberOfSides?=?7? var ?shapeDescription?=?shape.simpleDescription()? 通過init構(gòu)建對象,既可以使用self顯式引用成員字段(name),也可以隱式引用(numberOfSides)。
class ?NamedShape?{? ????var ?numberOfSides:?Int?=?0? ????var ?name:?String? ?? ????init(name:?String)?{? ????????self.name?=?name? ????}? ?? ????func?simpleDescription()?->?String?{? ????????return ? "A?shape?with?\(numberOfSides)?sides." ? ????}? }? 使用deinit進(jìn)行清理工作。
繼承和多態(tài) Swift支持繼承和多態(tài)(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?test?=?Square(sideLength:?5.2,?name:?"my?test?square" )? test.area()? test.simpleDescription()? 注意:如果這里的simpleDescription方法沒有被標(biāo)識為override,則會引發(fā)編譯錯誤。
屬性 為了簡化代碼,Swift引入了屬性(property),見下面的perimeter字段:
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?triagle?with?sides?of?length?\(sideLength)." ? ????}? }? var ?triangle?=?EquilateralTriangle(sideLength:?3.1,?name:? "a?triangle" )? triangle.perimeter? triangle.perimeter?=?9.9? triangle.sideLength? 注意:賦值器(setter)中,接收的值被自動命名為newValue。
willSet和didSet EquilateralTriangle的構(gòu)造器進(jìn)行了如下操作: 1.為子類型的屬性賦值。 2.調(diào)用父類型的構(gòu)造器。 3.修改父類型的屬性。 如果不需要計算屬性的值,但需要在賦值前后進(jìn)行一些操作的話,使用willSet和didSet:
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:? "another?test?shape" )? triangleAndSquare.square.sideLength? triangleAndSquare.square?=?Square(sideLength:?50,?name:?"larger?square" )? triangleAndSquare.triangle.sideLength? 從而保證triangle和square擁有相等的sideLength。
調(diào)用方法 Swift中,函數(shù)的參數(shù)名稱只能在函數(shù)內(nèi)部使用,但方法的參數(shù)名稱除了在內(nèi)部使用外還可以在外部使用(第一個參數(shù)除外),例如:
class ?Counter?{? ????var ?count:?Int?=?0? ????func?incrementBy(amount:?Int,?numberOfTimes?times:?Int)?{? ????????count?+=?amount?*?times? ????}? }? var ?counter?=?Counter()? counter.incrementBy(2,?numberOfTimes:?7)? 注意Swift支持為方法參數(shù)取別名:在上面的代碼里,numberOfTimes面向外部,times面向內(nèi)部。
?的另一種用途 使用可空值時,?可以出現(xiàn)在方法、屬性或下標(biāo)前面。如果?前的值為nil,那么?后面的表達(dá)式會被忽略,而原表達(dá)式直接返回nil,例如:
1? 2? 3? let?optionalSquare:?Square??=?Square(sideLength:?2.5,?name:?"optional?? square")? let?sideLength?=?optionalSquare?.sideLength? 當(dāng)optionalSquare為nil時,sideLength屬性調(diào)用會被忽略。
枚舉和結(jié)構(gòu) 枚舉 使用enum創(chuàng)建枚舉——注意Swift的枚舉可以關(guān)聯(lián)方法:
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())? ????????}? ????}? }? let?ace?=?Rank.Ace? let?aceRawValue?=?ace.toRaw()? 使用toRaw和fromRaw在原始(raw)數(shù)值和枚舉值之間進(jìn)行轉(zhuǎn)換:
if ?let?convertedRank?=?Rank.fromRaw(3)?{? ????let?threeDescription?=?convertedRank.simpleDescription()? }? 注意:枚舉中的成員值(member value)是實際的值(actual value),和原始值(raw value)沒有必然關(guān)聯(lián)。 一些情況下枚舉不存在有意義的原始值,這時可以直接忽略原始值:
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" ? ????????}? ????}? }? let?hearts?=?Suit.Hearts? let?heartsDescription?=?hearts.simpleDescription()? 除了可以關(guān)聯(lián)方法,枚舉還支持在其成員上關(guān)聯(lián)值,同一枚舉的不同成員可以有不同的關(guān)聯(lián)的值:
enum ?ServerResponse?{? ????case ?Result(String,?String)? ????case ?Error(String)? }? ?? let?success?=?ServerResponse.Result("6:00?am" ,? "8:09?pm" )? let?failure?=?ServerResponse.Error("Out?of?cheese." )? ?? switch ?success?{? ????case ?let?.Result(sunrise,?sunset):? ????????let?serverResponse?=?"Sunrise?is?at?\(sunrise)?and?sunset?is?at?\(sunset)." ? ????case ?let?.Error(error):? ????????let?serverResponse?=?"Failure...?\(error)" ? }? 結(jié)構(gòu) Swift使用struct關(guān)鍵字創(chuàng)建結(jié)構(gòu)。結(jié)構(gòu)支持構(gòu)造器和方法這些類的特性。結(jié)構(gòu)和類的最大區(qū)別在于:結(jié)構(gòu)的實例按值傳遞(passed by value),而類的實例按引用傳遞(passed by reference)。
struct?Card?{? ????var ?rank:?Rank? ????var ?suit:?Suit? ????func?simpleDescription()?->?String?{? ????????return ? "The?\(rank.simpleDescription())?of?\(suit.simpleDescription())" ? ????}? }? let?threeOfSpades?=?Card(rank:?.Three,?suit:?.Spades)? let?threeOfSpadesDescription?=?threeOfSpades.simpleDescription()? 協(xié)議(protocol)和擴(kuò)展(extension) 協(xié)議 Swift使用protocol定義協(xié)議:
protocol?ExampleProtocol?{? ????var ?simpleDescription:?String?{?get?}? ????mutating?func?adjust()? }? 類型、枚舉和結(jié)構(gòu)都可以實現(xiàn)(adopt)協(xié)議:
class ?SimpleClass:?ExampleProtocol?{? ????var ?simpleDescription:?String?=? "A?very?simple?class." ? ????var ?anotherProperty:?Int?=?69105? ????func?adjust()?{? ????????simpleDescription?+=?"?Now?100%?adjusted." ? ????}? }? var ?a?=?SimpleClass()? a.adjust()? let?aDescription?=?a.simpleDescription? ?? struct?SimpleStructure:?ExampleProtocol?{? ????var ?simpleDescription:?String?=? "A?simple?structure" ? ????mutating?func?adjust()?{? ????????simpleDescription?+=?"?(adjusted)" ? ????}? }? var ?b?=?SimpleStructure()? b.adjust()? let?bDescription?=?b.simpleDescription? 擴(kuò)展 擴(kuò)展用于在已有的類型上增加新的功能(比如新的方法或?qū)傩?#xff09;,Swift使用extension聲明擴(kuò)展:
extension?Int:?ExampleProtocol?{? ????var ?simpleDescription:?String?{? ????????return ? "The?number?\(self)" ? ????}? ????mutating?func?adjust()?{? ????????self?+=?42? ????}? }? 7.simpleDescription? 泛型(generics) Swift使用<>來聲明泛型函數(shù)或泛型類型:
func?repeat<ItemType>(item:?ItemType,?times:?Int)?->?ItemType[]?{? ????var ?result?=?ItemType[]()? ????for ?i? in ?0..times?{? ????????result?+=?item? ????}? ????return ?result? }? repeat("knock" ,?4)? Swift也支持在類、枚舉和結(jié)構(gòu)中使用泛型:
? enum ?OptionalValue<T>?{? ????case ?None? ????case ?Some(T)? }? var ?possibleInteger:?OptionalValue<Int>?=?.None? possibleInteger?=?.Some(100)? 有時需要對泛型做一些需求(requirements),比如需求某個泛型類型實現(xiàn)某個接口或繼承自某個特定類型、兩個泛型類型屬于同一個類型等等,Swift通過where描述這些需求:
func?anyCommonElements?<T,?U?where?T:?Sequence,?U:?Sequence,?T.GeneratorType.Element:?Equatable,?T.GeneratorType.Element?==?U.GeneratorType.Element>?(lhs:?T,?rhs:?U)?->?Bool?{? ????for ?lhsItem? in ?lhs?{? ????????for ?rhsItem? in ?rhs?{? ????????????if ?lhsItem?==?rhsItem?{? ????????????????return ? true ? ????????????}? ????????}? ????}? ????return ? false ? }? anyCommonElements([1,?2,?3],?[3])? Swift語言概覽就到這里,有興趣的朋友請進(jìn)一步閱讀The Swift Programming Language。 接下來聊聊個人對Swift的一些感受。
個人感受 注意:下面的感受純屬個人意見,僅供參考。
大雜燴 盡管我接觸Swift不足兩小時,但很容易看出Swift吸收了大量其它編程語言中的元素,這些元素包括但不限于: 屬性(Property)、可空值(Nullable type)語法和泛型(Generic Type)語法源自C#。 格式風(fēng)格與Go相仿(沒有句末的分號,判斷條件不需要括號)。 Python風(fēng)格的當(dāng)前實例引用語法(使用self)和列表字典聲明語法。 Haskell風(fēng)格的區(qū)間聲明語法(比如1..3,1...3)。 協(xié)議和擴(kuò)展源自O(shè)bjective-C(自家產(chǎn)品隨便用)。 枚舉類型很像Java(可以擁有成員或方法)。 class和struct的概念和C#極其相似。 注意這里不是說Swift是抄襲——實際上編程語言能玩的花樣基本就這些,況且Swift選的都是在我看來相當(dāng)不錯的特性。 而且,這個大雜燴有一個好處——就是任何其它編程語言的開發(fā)者都不會覺得Swift很陌生——這一點很重要。
拒絕隱式(Refuse implicity) Swift去除了一些隱式操作,比如隱式類型轉(zhuǎn)換和隱式方法重載這兩個坑,干的漂亮。
Swift的應(yīng)用方向 我認(rèn)為Swift主要有下面這兩個應(yīng)用方向:
教育 我指的是編程教育。現(xiàn)有編程語言最大的問題就是交互性奇差,從而導(dǎo)致學(xué)習(xí)曲線陡峭。相信Swift及其交互性極強(qiáng)的編程環(huán)境能夠打破這個局面,讓更多的人——尤其是青少年,學(xué)會編程。 這里有必要再次提到Brec Victor的Inventing on Principle,看了這個視頻你就會明白一個交互性強(qiáng)的編程環(huán)境能夠帶來什么。
應(yīng)用開發(fā) 現(xiàn)有的iOS和OS X應(yīng)用開發(fā)均使用Objective-C,而Objective-C是一門及其繁瑣(verbose)且學(xué)習(xí)曲線比較陡峭的語言,如果Swift能夠提供一個同現(xiàn)有Obj-C框架的簡易互操作接口,我相信會有大量的程序員轉(zhuǎn)投Swift;與此同時,Swift簡易的語法也會帶來相當(dāng)數(shù)量的其它平臺開發(fā)者。 總之,上一次某家大公司大張旗鼓的推出一門編程語言及其編程平臺還是在2000年(微軟推出C#),將近15年之后,蘋果推出Swift——作為開發(fā)者,我很高興能夠見證一門編程語言的誕生。
總結(jié)
以上是生活随笔 為你收集整理的来自苹果的编程语言——Swift简介 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。