WWDC 2014上苹果再次惊世骇俗的推出了新的编程语言Swift 雨燕, 这个消息会前没有半点风声的走露。消息发布当时,会场一片惊呼,相信全球看直播的码农们当时也感受脑壳被敲了一记闷棍吧。因而熬夜学习了Swift大法, 越看越想高呼 ” Swift大法好!“java
程序员,最讲究的就是实事求是和客观,下面就开始对比两种语言。c++
首先要强调的是,Swift绝对不是解释性语言,更不是脚本语言,它和Objective-C,C++同样,编译器最终会把它翻译成C语言,也就是 说编译器最终面对的其实都是C语言代码( 这是千真万确,无可置疑的!!!因此不要看它长的想脚本语言,其实它是比Java, C#要高效的多的C语言!!!),可是Swift的强大之处在于它站在全部语言的肩膀上,吸收全部语言的精华。程序员
这个系列咱们先谈谈几个最基本的语法变化:objective-c
但苹果不会这么自甘平庸,咱们知道Objective-C里方法的调用有种语法是其余主流语言没有的,那就是标签。咱们在使用java, C++, C, C#等语言时,若是使用 rect.set( 10, 20, 100, 500 ), 虽然在写set方法的时候,IDE有提示四个形参的含义,但写完后,这句代码中10, 20, 100, 500是社么意思? 因此代码的可读性就变的不好, 而Objective-C很完美的解决了这个问题 :编程
[ rect setX:10 y:20 width:100 height:500 ]
看看!多棒!Swift固然不会丢弃这么好的传统, 在Swift中是这个样子的swift
rect.set( 10, y:20, width:100, height:500 )
对于调用方法时,标签的使用须要注意如下两点:c#
1)全局函数的调用,不可使用标签api
2 ) 类的函数,第一个参数不能够加标签 编程语言
其实Swift中对类的定义和java, c#几乎同样,不再分头文件和.m文件了。ide
一个类的定义语法以下:
class Weapon { var name:NSString var power:int init( name:NSString, power:int ) { self.name = name self.power = power } func shoot( ) }
注意:Swift中的语句不须要分号结束.
其次,终于有构造函数和析构函数了!!!Objective-C也有?no no no!!!
Objective-C中没有构造函数,真正的构造函数是系统自动调用的,而不是强迫程序员去调用。之前要强迫程序员[ [ Obj alloc ] init ],如今终于终于终于系统自动调用了!
Weapon weapon = Weapon( name:“人间大炮”, power: 100000000000 )
我没有写错, 对的!如今和java,C#同样!虽然weapon是一个指针,但不要写那颗星号!!由于这颗星号吓死过好多人!“ 啥?指针?!!啊。。。。。”
C、 C++的程序员注意了,这个weapon对象不是分配在栈内存上的, 仍然是alloc出来的, 在堆上呢。
对于override在Java,C++,Objective-C中都有问题,举个栗子:
@interface Weapon -(void)shoot; @end @interface Gun : Weapon -(void)Shoot; @end
在大项目中常常会遇到这个问题,程序员的本意是但愿覆盖父类的shoot ,结果手潮。。。。写成了Shoot , 这既没有语法错误,也没有逻辑错误,结果在
Weapon* currentWeapon = [ Gun new ];
[currentWeapon shoot ] 中调用的倒是父类的shoot方法( 由于子类根本没有覆盖啦,子类大小写不当心写错了 ), 这种小错误若是出如今超大型项目种还真是很难找呢!!如今,Swift终于解决这个问题啦! 子类覆盖父类方法的时候,必定要在方法前写上override :
override func shoot{ }
这样,编译器一看方法前写了override, 它就会在父类中去查找是否有shoot方法, 若是你写错成override func Shoot, 那编译器就马上能发现报错啦!
系列(二)
系列一发表后,有人不一样意个人关于 #swift会取代objective-c#的论点,在这里我想强调两点:
1)Swift其实就是Objective-C的文本变种,对于这门全新的语言,苹果作的工做其实远没有咱们想像的艰巨。LLVM编译器作工做只是 先把swift翻译成Objctive-C代码,而后再把Objective-C代码翻译成C语言代码,而后再把C语言代码翻译成汇编,最终翻译成机器 码。至于为何编译器厂商这么绕,不直接把本身的语言翻译成汇编和机器码,那是因为现有的语言编译器(Objective-C, C )已经很是成熟,而高级语言间的文本转换开发成本和维护成本都极其小。Swift为何要翻译成Objective-C,是因为Swift仍然须要 Objective-C中辛苦构建的ARC,GCD 等环境。
2)既然Swift代码最终会被LLVM翻译成Objective-C, 那Swift语言还有什么意义?想一想ARC刚出来的时候你们的反应吧,不少人和今天的反应同样,认为我是资深的objective-c马仔了,我深谙内存 管理之道,不停的写[ obj release ], [ obj autoRelease] 很牛,只有那些初学者才会用ARC呢。结果就是不到一年,ARC统治了整个马仔界,由于咱们马仔关注的应该是业务逻辑,而不该该把精力分散在语法等低级问 题上,语法消耗咱们的时间越少,这门语言就越成功。
既然Swift其实就是Objective-C, 对入门者而言远比Objective-C好学,对资深开发者来讲又能节约不少无谓的低级重复的机械代码(这些代码在LLVM翻译成Objective-C 时,编译器自动帮你写上)。我是想不出任何一点Swift不替换Objective-C的理由呢。
好吧,争论放置一边不表,咱们从头来看swift到底进化到什么程度。
1)语句不须要分号结束,变量若是有初始化就不须要类型
var n = 22
对于编译器而言,既然你都初始化为22了,它固然明白n是int , 你都打回车了, 它固然知道这是语句的结束,因此LLVM毫无压力的把它翻译成
int n = 22;
固然对于多个语句放一行,那编译器就没有办法了, 你仍是要用分号来结束语句。若是没有初始化,你也能够手工指定变量类型
var n = 22; var hero:Hero
因此看上去是无类型变量,实质上仍是强类型的( 编译器给你作了 ).
若是是常量的话, 用let
let PI = 3.1415926
这里的PI 就是常量, 如今想一想,之前的强类型高级语言真是傻到无语啊,let PI = 3.1415926 , PI 都这么明显是个double, 为啥还要程序员再写double ?!
2)函数的定义
func test( p1: int, p2: int ) { }
调用: test( 25 , 100 ) //注意:全局函数的调用,参数不能加标签
若是有返回值, 返回类型用符号 “ -> ” 表示
func add( p1: int, p2 : int )->int { return p1+p2 }
3)类的定义
再也不分头文件和m文件了!这点和java, C#如出一辙
class Person { var name:String var age = 0 init( name:String , age:int ) { self.name = name; self.age = age; } func description( )->String { return “Name:\( self.name ) ; Age: \( age )”; } }
注意终于有构造函数了!!init 是系统自动调用的, 不须要程序员手工调用。因此它写起来和普通函数也有区别,前边不能加func。 编译器为何要这样作?由于若是init也容许前面加上func, 万一程序员不当心把init函数名写错了, 写成func Inot( ),编译器就彻底不知道它是程序员想写的构造函数。如今构造函数前不加func , 若是你写成Inot( ) 。 编译器一看前面没有func知道你要写构造,可函数名又不是init, 编译器就知道你不当心写错了就能够马上报错啦!!
4)#可选变量# ---全部高级语言一开始就遇到的难题
好比客户须要提供一个最终的API, 客户给你一个数据源, 须要在数据源里找到名字是“jack.xu”的学员成绩。这个api的设计应该是这样的:
int FindScoreByName( DataSource* source, string* name );
问题来了,若是“jack.xu”的学员根本不存在,应该返回啥? 返回0?那确定不对,由于0有可能也是学员的成绩。固然,若是返回的是类的对象,直接返回 NULL , 调用者就知道没有找到,如今是基本数据类型,返回NULL 其实就是0,怎么办?(在C,C++中的规范作法是 返回bool表示是否找到,而成绩经过形参来传递 ,其余高级语言中能够封装一个小类/包裹类 )
Swift针对这个问题,专门设计了一个叫”optional value(可选变量)” 的变量,它就是为了解决这个问题的。
语法:
var n : UInt ? = 5 或者 var n ? = 5
这里的?表示n 是个可选变量, 也就是说 n 有可能不存在, 什么状况下n不存在呢?
若是你这样写:
var n : UInt ?
此外,须要注意的是swift语法中,nil 并非0 , 而是一个NilType类型的变量
因此上面提到的那个问题就能够很容易解决了
func FindScoreByName( source:DataSource, name:String )->UInt? //返回的是可选变量 { var score : UInt ?; //此时 score 的变量没有分配内存,也就是说score为nil if( source.HasStudent( name: name ) ) score = source[ name ]. score; //这里score才分配内存; return score; //若是没有找到学生信息, score的内存一直没被分配 }