转自:http://www.cocoachina.com/industry/20140603/8653.html
前言
接下来进入正题。
Swift是什么?
Swift是苹果于WWDC 2014发布的编程语言,这里引用
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用来写iOS和OS X程序。(估计也不会支持其它屌丝系统)
Swift吸取了C和Objective-C的优点,且更加强大易用。
Swift可以使用现有的Cocoa和Cocoa Touch框架。
Swift语言概览
基本概念
注:这一节的代码源自
The Swift Programming Language中的A Swift Tour。
Hello,world
- println("Hello,world")
变量与常量
Swift使用var声明变量,let声明常量。
- varmyVariable=42
- myVariable=50
- letmyConstant=42
类型推导
- letexplicitDouble:Double=70
- letlabel="Thewidthis"
- letwidth=94
- letwidthLabel=label+String(width)
字符串格式化
Swift使用\(item)的形式进行字符串格式化:
- letapples=3
- letoranges=5
- letappleSummary="Ihave\(apples)apples."
- letappleSummary="Ihave\(apples+oranges)piecesoffruit."
数组和字典
Swift使用[]操作符声明数组(array)和字典(dictionary):
- varshoppingList=["catfish","water","tulips","bluepaint"]
- shoppingList[1]="bottleofwater"
- varoccupations=[
- "Malcolm":"Captain",
- "Kaylee":"Mechanic",
- ]
- occupations["Jayne"]="PublicRelations"
一般使用初始化器(initializer)语法创建空数组和空字典:
- letemptyArray=String[]()
- letemptyDictionary=Dictionary<String,Float>()
如果类型信息已知,则可以使用[]声明空数组,使用[:]声明空字典。
控制流
概览
Swift的条件语句包含if和switch,循环语句包含for-in、for、while和do-while,循环/判断条件不需要括号,但循环/判断体(body)必需括号:
可空类型
结合if和let,可以方便的处理可空变量(nullable variable)。对于空值,需要在类型声明后添加?显式标明该类型可空。
- varoptionalString:String?="Hello"
- optionalString==nil
- varoptionalName:String?="JohnAppleseed"
- vargretting="Hello!"
- ifletname=optionalName{
- gretting="Hello,\(name)"
- }
灵活的switch
Swift中的switch支持各种各样的比较操作:
- letvegetable="redpepper"
- switchvegetable{
- case"celery":
- letvegetableComment="Addsomeraisinsandmakeantsonalog."
- case"cucumber","watercress":
- letvegetableComment="Thatwouldmakeagoodteasandwich."
- caseletxwherex.hasSuffix("pepper"):
- letvegetableComment="Isitaspicy\(x)?"
- default:
- letvegetableComment="Everythingtastesgoodinsoup."
- }
其它循环
for-in除了遍历数组也可以用来遍历字典:
- letinterestingNumbers=[
- "Prime":[2,3,5,7,11,13],
- "Fibonacci":[1,1,2,8],
- "Square":[1,4,9,16,25],
- ]
- varlargest=0
- for(kind,numbers)ininterestingNumbers{
- fornumberinnumbers{
- ifnumber>largest{
- largest=number
- }
- }
- }
- largest
while循环和do-while循环:
- varn=2
- whilen<100{
- n=n*2
- }
- n
- varm=2
- do{
- m=m*2
- }whilem<100
- m
函数和闭包
Swift使用func关键字声明函数:
- funcgreet(name:String,day:String)->String{
- return"Hello\(name),todayis\(day)."
- }
- greet("Bob","Tuesday")
通过元组(Tuple)返回多个值:
- funcgetGasPrices()->(Double,Double,Double){
- return(3.59,3.69,3.79)
- }
- getGasPrices()
- funcsumOf(numbers:Int...)->Int{
- varsum=0
- fornumberinnumbers{
- sum+=number
- }
- returnsum
- }
- sumOf()
- sumOf(42,597,12)
- funcreturnFifteen()->Int{
- vary=10
- funcadd(){
- y+=5
- }
- add()
- returny
- }
- returnFifteen()
作为头等对象,函数既可以作为返回值,也可以作为参数传递:
- funcmakeIncrementer()->(Int->Int){
- funcaddOne(number:Int)->Int{
- return1+number
- }
- returnaddOne
- }
- varincrement=makeIncrementer()
- increment(7)
闭包
本质来说,函数是特殊的闭包,Swift中可以利用{}声明匿名闭包:
- numbers.map({
- (number:Int)->Intin
- letresult=3*number
- returnresult
- })
当闭包的类型已知时,可以使用下面的简化写法:
- numbers.map({numberin3*number})
- sort([1,12,2]){$0>$1}
类和对象
创建和使用类
- classShape{
- varnumberOfSides=0
- funcsimpleDescription()->String{
- return"Ashapewith\(numberOfSides)sides."
- }
- }
- varshape=Shape()
- shape.numberOfSides=7
- varshapeDescription=shape.simpleDescription()
通过init构建对象,既可以使用self显式引用成员字段(name),也可以隐式引用(numberOfSides)。
- classNamedShape{
- varnumberOfSides:Int=0
- varname:String
- init(name:String){
- self.name=name
- }
- funcsimpleDescription()->String{
- return"Ashapewith\(numberOfSides)sides."
- }
- }
使用deinit进行清理工作。
继承和多态
- classSquare:NamedShape{
- varsideLength:Double
- init(sideLength:Double,name:String){
- self.sideLength=sideLength
- super.init(name:name)
- numberOfSides=4
- }
- funcarea()->Double{
- returnsideLength*sideLength
- }
- overridefuncsimpleDescription()->String{
- return"Asquarewithsidesoflength\(sideLength)."
- }
- }
- lettest=Square(sideLength:5.2,name:"mytestsquare")
- test.area()
- test.simpleDescription()
- classEquilateralTriangle:NamedShape{
- varsideLength:Double=0.0
- init(sideLength:Double,name:String){
- self.sideLength=sideLength
- super.init(name:name)
- numberOfSides=3
- }
- varperimeter:Double{
- get{
- return3.0*sideLength
- }
- set{
- sideLength=newValue/3.0
- }
- }
- overridefuncsimpleDescription()->String{
- return"Anequilateraltriaglewithsidesoflength\(sideLength)."
- }
- }
- vartriangle=EquilateralTriangle(sideLength:3.1,name:"atriangle")
- triangle.perimeter
- triangle.perimeter=9.9
- triangle.sideLength
注意:赋值器(setter)中,接收的值被自动命名为newValue。
willSet和didSet
1.为子类型的属性赋值。
如果不需要计算属性的值,但需要在赋值前后进行一些操作的话,使用willSet和didSet:
- classTriangleAndSquare{
- vartriangle:EquilateralTriangle{
- willSet{
- square.sideLength=newValue.sideLength
- }
- }
- varsquare:Square{
- willSet{
- triangle.sideLength=newValue.sideLength
- }
- }
- init(size:Double,name:String){
- square=Square(sideLength:size,name:name)
- triangle=EquilateralTriangle(sideLength:size,name:name)
- }
- }
- vartriangleAndSquare=TriangleAndSquare(size:10,name:"anothertestshape")
- triangleAndSquare.square.sideLength
- triangleAndSquare.square=Square(sideLength:50,name:"largersquare")
- triangleAndSquare.triangle.sideLength
从而保证triangle和square拥有相等的sideLength。
- classCounter{
- varcount:Int=0
- funcincrementBy(amount:Int,numberOfTimestimes:Int){
- count+=amount*times
- }
- }
- varcounter=Counter()
- counter.incrementBy(2,numberOfTimes:7)
?的另一种用途
- 1
- 2
- 3
- letoptionalSquare:Square?=Square(sideLength:2.5,name:"optional
- square")
- letsideLength=optionalSquare?.sideLength
枚举和结构
枚举
使用enum创建枚举——注意Swift的枚举可以关联方法:
- enumRank:Int{
- caseAce=1
- caseTwo,Three,Four,Five,Six,Seven,Eight,Nine,Ten
- caseJack,Queen,King
- funcsimpleDescription()->String{
- switchself{
- case.Ace:
- return"ace"
- case.Jack:
- return"jack"
- case.Queen:
- return"queen"
- case.King:
- return"king"
- default:
- returnString(self.toRaw())
- }
- }
- }
- letace=Rank.Ace
- letaceRawValue=ace.toRaw()
- ifletconvertedRank=Rank.fromraw(3){
- letthreeDescription=convertedRank.simpleDescription()
- }
注意:枚举中的成员值(member value)是实际的值(actual value),和原始值(raw value)没有必然关联。
一些情况下枚举不存在有意义的原始值,这时可以直接忽略原始值:
- enumSuit{
- caseSpades,Hearts,Diamonds,Clubs
- funcsimpleDescription()->String{
- switchself{
- case.Spades:
- return"spades"
- case.Hearts:
- return"hearts"
- case.Diamonds:
- return"diamonds"
- case.Clubs:
- return"clubs"
- }
- }
- }
- lethearts=Suit.Hearts
- letheartsDescription=hearts.simpleDescription()
- enumServerResponse{
- caseResult(String,String)
- caseError(String)
- }
- letsuccess=ServerResponse.Result("6:00am","8:09pm")
- letfailure=ServerResponse.Error("Outofcheese.")
- switchsuccess{
- caselet.Result(sunrise,sunset):
- letserverResponse="Sunriseisat\(sunrise)andsunsetisat\(sunset)."
- caselet.Error(error):
- letserverResponse="Failure...\(error)"
- }
结构
Swift使用struct关键字创建结构。结构支持构造器和方法这些类的特性。结构和类的最大区别在于:结构的实例按值传递(passed by value),而类的实例按引用传递(passed by reference)。
- structCard{
- varrank:Rank
- varsuit:Suit
- funcsimpleDescription()->String{
- return"The\(rank.simpleDescription())of\(suit.simpleDescription())"
- }
- }
- letthreeOfSpades=Card(rank:.Three,suit:.Spades)
- letthreeOfSpadesDescription=threeOfSpades.simpleDescription()
协议(protocol)和扩展(extension)
协议
Swift使用protocol定义协议:
- protocolExampleProtocol{
- varsimpleDescription:String{get}
- mutatingfuncadjust()
- }
类型、枚举和结构都可以实现(adopt)协议:
- classSimpleClass:ExampleProtocol{
- varsimpleDescription:String="Averysimpleclass."
- varanotherProperty:Int=69105
- funcadjust(){
- simpleDescription+="Now100%adjusted."
- }
- }
- vara=SimpleClass()
- a.adjust()
- letaDescription=a.simpleDescription
- structSimpleStructure:ExampleProtocol{
- varsimpleDescription:String="Asimplestructure"
- mutatingfuncadjust(){
- simpleDescription+="(adjusted)"
- }
- }
- varb=SimpleStructure()
- b.adjust()
- letbDescription=b.simpleDescription
扩展
- extensionInt:ExampleProtocol{
- varsimpleDescription:String{
- return"Thenumber\(self)"
- }
- mutatingfuncadjust(){
- self+=42
- }
- }
- 7.simpleDescription
泛型(generics)
Swift使用<>来声明泛型函数或泛型类型:
- funcrepeat<ItemType>(item:ItemType,times:Int)->ItemType[]{
- varresult=ItemType[]()
- foriin0..times{
- result+=item
- }
- returnresult
- }
- repeat("knock",4)
Swift也支持在类、枚举和结构中使用泛型:
- //ReimplementtheSwiftstandardlibrary'soptionaltype
- enumOptionalValue<T>{
- caseNone
- caseSome(T)
- }
- varpossibleInteger:OptionalValue<Int>=.None
- possibleInteger=.some(100)
有时需要对泛型做一些需求(requirements),比如需求某个泛型类型实现某个接口或继承自某个特定类型、两个泛型类型属于同一个类型等等,Swift通过where描述这些需求:
- funcanyCommonElements<T,UwhereT:Sequence,U:Sequence,T.GeneratorType.Element:Equatable,T.GeneratorType.Element==U.GeneratorType.Element>(lhs:T,rhs:U)->Bool{
- forlhsIteminlhs{
- forrhsIteminrhs{
- iflhsItem==rhsItem{
- returntrue
- }
- }
- }
- returnfalse
- }
- anyCommonElements([1,3],[3])
Swift语言概览就到这里,有兴趣的朋友请进一步阅读The Swift Programming Language。
接下来聊聊个人对Swift的一些感受。
个人感受
注意:下面的感受纯属个人意见,仅供参考。
大杂烩
尽管我接触Swift不足两小时,但很容易看出Swift吸收了大量其它编程语言中的元素,这些元素包括但不限于:
1.属性(Property)、可空值(Nullable type)语法和泛型(Generic Type)语法源自C#。
2.格式风格与Go相仿(没有句末的分号,判断条件不需要括号)。
3.Python风格的当前实例引用语法(使用self)和列表字典声明语法。
4.Haskell风格的区间声明语法(比如1..3,1...3)。
5.协议和扩展源自Objective-C(自家产品随便用)。
6.枚举类型很像Java(可以拥有成员或方法)。
7.class和struct的概念和C#极其相似。
注意这里不是说Swift是抄袭——实际上编程语言能玩的花样基本就这些,况且Swift选的都是在我看来相当不错的特性。
而且,这个大杂烩有一个好处——就是任何其它编程语言的开发者都不会觉得Swift很陌生——这一点很重要。
拒绝隐式(Refuse implicity)
Swift的应用方向
我认为Swift主要有下面这两个应用方向:
教育
我指的是编程教育。现有编程语言最大的问题就是交互性奇差,从而导致学习曲线陡峭。相信Swift及其交互性极强的编程环境能够打破这个局面,让更多的人——尤其是青少年,学会编程。
这里有必要再次提到Brec Victor的Inventing on Principle,看了这个视频你就会明白一个交互性强的编程环境能够带来什么。
应用开发
现有的iOS和OS X应用开发均使用Objective-C,而Objective-C是一门及其繁琐(verbose)且学习曲线比较陡峭的语言,如果Swift能够提供一个同现有Obj-C框架的简易互操作接口,我相信会有大量的程序员转投Swift;与此同时,Swift简易的语法也会带来相当数量的其它平台开发者。
总之,上一次某家大公司大张旗鼓的推出一门编程语言及其编程平台还是在2000年(微软推出C#),将近15年之后,苹果推出Swift——作为开发者,我很高兴能够见证一门编程语言的诞生。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。