WWDC 2014上苹果再次惊世骇俗的推出了新的编程语言Swift 雨燕, 这个消息会前没有半点风声的走漏。消息发布当时,会场一片惊呼,相信全球看直播的码农们当时也感觉脑袋被敲了一记闷棍吧。于是熬夜学习了Swift大法, 越看越想高呼 ” Swift大法好!“

程序员,最讲究的就是实事求是和客观,下面就开始对比两种语言。

首先要强调的是,Swift绝对不是解释性语言,更不是脚本语言,它和Objective-C,C++一样,编译器最终会把它翻译成C语言,也就是 说编译器最终面对的其实都是C语言代码( 这是千真万确,不容置疑的!!!所以不要看它长的想脚本语言,其实它是比Java, C#要高效的多的C语言!!!),但是Swift的强大之处在于它站在所有语言的肩膀上,吸取所有语言的精华。

这个系列我们先谈谈几个最基本的语法变化:

  1. Swift终于放弃了Objective-C那幺蛾子般的 [ obj method:x1 with:x2] 的语法,终于跟随了大流,变成了obj.method( )的顺眼模式。虽然对于Objective-C的程序员来说,这些[ ]看上去特显酷 , 你们知道就是这个中括弧吓跑了多少c++, java , c#的程序员嘛?所以说这个小小的变化,可以让苹果的开发更平易近人,对有其他开发语言基础的人来说更友好。

但苹果不会这么自甘平庸,我们知道Objective-C里方法的调用有种语法是其他主流语言没有的,那就是标签。我们在使用java, C++, C, C#等语言时,如果使用 rect.set( 10, 20, 100, 500 ), 虽然在写set方法的时候,IDE有提示四个形参的含义,但写完后,这句代码中10, 20, 100, 500是社么意思? 所以代码的可读性就变的很差, 而Objective-C很完美的解决了这个问题 :

  1. [ rect setX:10 y:20 width:100 height:500 ]
[ rect setX:10 y:20 width:100 height:500 ]

看看!多棒!Swift当然不会丢弃这么好的传统, 在Swift中是这个样子的

  1. rect.set( 10, y:20, width:100, height:500 )
rect.set( 10, y:20, width:100, height:500 )

对于调用方法时,标签的使用需要注意以下两点:

1)全局函数的调用,不可以使用标签

  1. fun( 11, 22 , 33 ) //正确
  2. fun( n1:11, n2: 22, n3: 33 ) //错误

2 ) 类的函数,第一个参数不可以加标签

  1. rect.set( 100, y:100, width:300, height: 200 ) //正确
  2. rect.set( x:100, y:100, width:300, height: 200 ) //错误

其实Swift中对类的定义和java, c#几乎一样,再也不分头文件和.m文件了。

一个类的定义语法如下:

  1. class Weapon
  2. {
  3. var name:NSString
  4. var power:int
  5. init( name:NSString, power:int )
  6. {
  7. self.name = name
  8. self.power = power
  9. }
  10. func shoot( )
  11. }
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 ],现在终于终于终于系统自动调用了!

  1. Weapon weapon = Weapon( name:“人间大炮”, power: 100000000000 )
Weapon weapon = Weapon( name:“人间大炮”, power: 100000000000 )

我没有写错, 对的!现在和java,C#一样!虽然weapon是一个指针,但不要写那颗星号!!因为这颗星号吓死过好多人!“ 啥?指针?!!啊。。。。。”

C、 C++的程序员注意了,这个weapon对象不是分配在栈内存上的, 仍然是alloc出来的, 在堆上呢。

  1. 最期待的语法终于加入了!

对于override在Java,C++,Objective-C中都有问题,举个栗子:

  1. @interface Weapon
  2. -(void)shoot;
  3. @end
  4. @interface Gun : Weapon
  5. -(void)Shoot;
  6. @end
@interface Weapon
-(void)shoot;
@end
@interface Gun : Weapon
-(void)Shoot;
@end

在大项目中经常会遇到这个问题,程序员的本意是希望覆盖父类的shoot ,结果手潮。。。。写成了Shoot , 这既没有语法错误,也没有逻辑错误,结果在

  1. Weapon*  currentWeapon = [ Gun new ];
Weapon*  currentWeapon = [ Gun new ];

[currentWeapon shoot ] 中调用的却是父类的shoot方法( 因为子类根本没有覆盖啦,子类大小写不小心写错了 ), 这种小错误如果出现在超大型项目种还真是很难找呢!!现在,Swift终于解决这个问题啦! 子类覆盖父类方法的时候,一定要在方法前写上override :

  1. override func shoot{
  2. }
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)语句不需要分号结束,变量如果有初始化就不需要类型

  1. var n = 22
var n = 22

对于编译器而言,既然你都初始化为22了,它当然明白n是int , 你都打回车了, 它当然知道这是语句的结束,所以LLVM毫无压力的把它翻译成

  1. int n = 22;
int n = 22;

当然对于多个语句放一行,那编译器就没有办法了, 你还是要用分号来结束语句。如果没有初始化,你也可以手工指定变量类型

  1. var n = 22; var hero:Hero
var n = 22; var hero:Hero

所以看上去是无类型变量,实质上还是强类型的( 编译器给你做了 ).

如果是常量的话, 用let

  1. let PI = 3.1415926
let PI = 3.1415926

这里的PI 就是常量, 现在想想,以前的强类型高级语言真是傻到无语啊,let PI = 3.1415926 , PI  都这么明显是个double, 为啥还要程序员再写double ?!

2)函数的定义

  1. func test( p1: int, p2: int )
  2. {
  3. }
func test( p1: int, p2: int )
{
}



调用: test( 25 , 100 ) //注意:全局函数的调用,参数不能加标签

如果有返回值, 返回类型用符号 “ -> ” 表示

  1. func  add( p1: int, p2 : int )->int
  2. {
  3. return p1+p2
  4. }
func  add( p1: int, p2 : int )->int
{
return p1+p2
}

3)类的定义

不再分头文件和m文件了!这点和java, C#一模一样

  1. class Person
  2. {
  3. var    name:String
  4. var    age = 0
  5. init( name:String , age:int )
  6. {
  7. self.name = name;
  8. self.age = age;
  9. }
  10. func description( )->String
  11. {
  12. return “Name:\( self.name ) ; Age: \( age )”;
  13. }
  14. }
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的设计应该是这样的:

  1. int FindScoreByName( DataSource*  source, string* name );
int FindScoreByName( DataSource*  source, string* name );

问题来了,如果“jack.xu”的学员根本不存在,应该返回啥? 返回0?那肯定不对,因为0有可能也是学员的成绩。当然,如果返回的是类的对象,直接返回 NULL , 调用者就知道没有找到,现在是基本数据类型,返回NULL 其实就是0,怎么办?(在C,C++中的规范做法是 返回bool表示是否找到,而成绩通过形参来传递 ,其他高级语言中可以封装一个小类/包裹类 )

Swift针对这个问题,专门设计了一个叫”optional value(可选变量)”  的变量,它就是为了解决这个问题的。

语法:

  1. var n : UInt ? = 5    或者  var n ? = 5
var n : UInt ? = 5    或者  var n ? = 5

这里的?表示n 是个可选变量, 也就是说 n 有可能不存在, 什么情况下n不存在呢?

如果你这样写:

  1. var n : UInt ?
var n : UInt ?

此外,需要注意的是swift语法中,nil 并不是0 , 而是一个NilType类型的变量

所以上面提到的那个问题就可以很容易解决了

  1. func FindScoreByName( source:DataSource, name:String )->UInt?  //返回的是可选变量
  2. {
  3. var score : UInt ?; //此时 score 的变量没有分配内存,也就是说score为nil
  4. if( source.HasStudent( name: name ) )
  5. score = source[ name ]. score;  //这里score才分配内存;
  6. return score; //如果没有找到学生信息, score的内存一直没被分配
  7. }
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的内存一直没被分配
}

Swift与Objective-C的对比的更多相关文章

  1. IOS-Swift、Objective-C、C++混合编程

    1.Objective-C调用C++代码 后缀为m文件的是Objective-C的执行文件,而后缀为mm文件的是Objective-C++文件. 直接在Objective-C中是无法调用C++代码的, ...

  2. Swift 与 Kotlin 的简单对比

    一位国外的程序员认为 Swift 的语法与 Kotlin 相似,并整理了一些 Swift 和 Kotlin 的对比,下面是一些例子,大家不妨也看看. BASICS Hello World Swift ...

  3. Swift与Objective-C中的闭包

    Swift Code: func makeIncrementor(forIncrement amount: Int) -> (() -> Int,() -> Int) { func ...

  4. Swift调用Objective C的FrameWork

    很多Github的库经过很多年的发展,源码都是OC写的,,所以,用Swift调用OC的库就是开发中难免遇到的的一个问题,本文以AFNetworking为例,讲解如何跨语言调用. 第一步 创建一个空的工 ...

  5. Swift和Objective C关于字符串的一个小特性

    一.Unicode的一个小特性 首先,Unicode规定了许多code point,每一个code point表示一个字符.如\u0033表示字符"3",\u864e表示字符&qu ...

  6. 作为一个iOS Developer 为什么我不用Swift?

    1.开始 在去年这个时候接手了一个iOS项目,项目主用Swift语言进行开发,对于部分第三方Objective C开源库则使用bridge的方式进行调用 当时项目的规模大概是不超过15个页面,功能也比 ...

  7. Swift 和 C# 的语法比较

    昨天看到Jacob Leverich 写了一篇文章 Swift is a lot like Scala 介绍Swift 和 Scala 的语法对比,从这篇文章的确可以看到Swift 的语法和 Scal ...

  8. iOS开发Swift篇—(二)变量和常量

    iOS开发Swift篇—(二)变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3.9倍 ...

  9. 李洪强iOS开发Swift篇—02_变量和常量

    李洪强iOS开发Swift篇—02_变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3. ...

  10. [转]swift 学习资源 大集合

    今天看到了一个swift的学习网站,里面收集了很多学习资源 [转自http://blog.csdn.net/sqc3375177/article/details/29206779] Swift 介绍 ...

随机推荐

  1. C#中登录验证FormsAuthentication

    1:前台编写一个登录界面,这里为了简化,只有用户名和密码 代码如下: <form method="post" action="/User/CheckLogin&qu ...

  2. javascript一些常用操作

    一:验证日期 1:日期必须满足yyyy-MM-dd格式 2:日期必须是合法的日期,如2016-02-30就是不存在 //验证就诊日期 function checkVisitDate(date){ va ...

  3. [改善Java代码]推荐使用枚举定义常量

    枚举和注解都是在Java1.5中引入的,虽然他们是后起之秀,但是功能不容小觑,枚举改变了常量的声明方式,注解耦合了数据和代码. 建议83:推荐使用枚举定义常量 一.分析 常量的声明是每一个项目中不可或 ...

  4. 关于Eclipse插件之IWorkbench IWorkbenchWindow IWorkbenchPage |WorkbenchPart......等的总结

    1..IWorkbench: workbench是eclipse用户界面中最底层的对象,它建立在Display之上,包含一个或多个IWorkbenchWindow,用于向终端用户呈现信息 当你的wor ...

  5. MSP430常见问题之看门狗及定时器类

    Q1. 定时器两个中断TAIE 和CCIE,有什么区别?两个中断的中断向量一样吗?A1:TAIE 和CCIE指的是不同事件.TAIE指TAR 计数器溢出,从65535 到0 的变化,由TAIFG 引起 ...

  6. eclipse svn重定位(relocate)

    eclipse 中项目svn 重定向 How to properly perform an SVN relocate on Zend for Eclipse 在eclipse中项目的svn 重定位(r ...

  7. Android Device Orientation

    最近在处理相机拍照的方向问题,在Android Device的Orientation问题上有了些疑问,就顺便写个Demo了解下Android Device Orientation究竟是怎么个判断. A ...

  8. JSP之session

    index.jsp: <form id="form1" name="form1" method="post" action=" ...

  9. 【转】C#绝对新手之C#中的多线程小结

    大概有4种方法: Dispatcher.异步委托.手动多线程.BackgroundWorker,另外还有一个DispatcherTimer,是定时器. 其中Dispatcher与DispatcherT ...

  10. 在Java中弹出位于其他类的由WindowsBuilder创建的JFrameApplicationWIndow

    我们一般在使用Java弹出窗体的时候,一般是使用Jdialog这个所谓的"对话框类".但是,如果你不是初学者或研究员,而会在使用Java进行swing项目的开发,那么你很可能用到一 ...