Swift与Objective-C的对比
WWDC 2014上苹果再次惊世骇俗的推出了新的编程语言Swift 雨燕, 这个消息会前没有半点风声的走漏。消息发布当时,会场一片惊呼,相信全球看直播的码农们当时也感觉脑袋被敲了一记闷棍吧。于是熬夜学习了Swift大法, 越看越想高呼 ” Swift大法好!“
程序员,最讲究的就是实事求是和客观,下面就开始对比两种语言。
首先要强调的是,Swift绝对不是解释性语言,更不是脚本语言,它和Objective-C,C++一样,编译器最终会把它翻译成C语言,也就是 说编译器最终面对的其实都是C语言代码( 这是千真万确,不容置疑的!!!所以不要看它长的想脚本语言,其实它是比Java, C#要高效的多的C语言!!!),但是Swift的强大之处在于它站在所有语言的肩膀上,吸取所有语言的精华。
这个系列我们先谈谈几个最基本的语法变化:
- 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很完美的解决了这个问题 :
- [ rect setX:10 y:20 width:100 height:500 ]
[ rect setX:10 y:20 width:100 height:500 ]
看看!多棒!Swift当然不会丢弃这么好的传统, 在Swift中是这个样子的
- rect.set( 10, y:20, width:100, height:500 )
rect.set( 10, y:20, width:100, height:500 )
对于调用方法时,标签的使用需要注意以下两点:
1)全局函数的调用,不可以使用标签
- fun( 11, 22 , 33 ) //正确
- fun( n1:11, n2: 22, n3: 33 ) //错误
2 ) 类的函数,第一个参数不可以加标签
- rect.set( 100, y:100, width:300, height: 200 ) //正确
- rect.set( x:100, y:100, width:300, height: 200 ) //错误
其实Swift中对类的定义和java, c#几乎一样,再也不分头文件和.m文件了。
一个类的定义语法如下:
- class Weapon
- {
- var name:NSString
- var power:int
- init( name:NSString, power:int )
- {
- self.name = name
- self.power = power
- }
- func shoot( )
- }
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 )
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
@interface Weapon
-(void)shoot;
@end
@interface Gun : Weapon
-(void)Shoot;
@end
在大项目中经常会遇到这个问题,程序员的本意是希望覆盖父类的shoot ,结果手潮。。。。写成了Shoot , 这既没有语法错误,也没有逻辑错误,结果在
- Weapon* currentWeapon = [ Gun new ];
Weapon* currentWeapon = [ Gun new ];
[currentWeapon shoot ] 中调用的却是父类的shoot方法( 因为子类根本没有覆盖啦,子类大小写不小心写错了 ), 这种小错误如果出现在超大型项目种还真是很难找呢!!现在,Swift终于解决这个问题啦! 子类覆盖父类方法的时候,一定要在方法前写上override :
- override func shoot{
- }
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
var n = 22
对于编译器而言,既然你都初始化为22了,它当然明白n是int , 你都打回车了, 它当然知道这是语句的结束,所以LLVM毫无压力的把它翻译成
- int n = 22;
int n = 22;
当然对于多个语句放一行,那编译器就没有办法了, 你还是要用分号来结束语句。如果没有初始化,你也可以手工指定变量类型
- var n = 22; var hero:Hero
var n = 22; var hero:Hero
所以看上去是无类型变量,实质上还是强类型的( 编译器给你做了 ).
如果是常量的话, 用let
- let PI = 3.1415926
let PI = 3.1415926
这里的PI 就是常量, 现在想想,以前的强类型高级语言真是傻到无语啊,let PI = 3.1415926 , PI 都这么明显是个double, 为啥还要程序员再写double ?!
2)函数的定义
- func test( p1: int, p2: int )
- {
- }
func test( p1: int, p2: int )
{
}
调用: test( 25 , 100 ) //注意:全局函数的调用,参数不能加标签
如果有返回值, 返回类型用符号 “ -> ” 表示
- func add( p1: int, p2 : int )->int
- {
- return p1+p2
- }
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 )”;
- }
- }
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 );
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
var n : UInt ? = 5 或者 var n ? = 5
这里的?表示n 是个可选变量, 也就是说 n 有可能不存在, 什么情况下n不存在呢?
如果你这样写:
- var n : UInt ?
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的内存一直没被分配
- }
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的对比的更多相关文章
- IOS-Swift、Objective-C、C++混合编程
1.Objective-C调用C++代码 后缀为m文件的是Objective-C的执行文件,而后缀为mm文件的是Objective-C++文件. 直接在Objective-C中是无法调用C++代码的, ...
- Swift 与 Kotlin 的简单对比
一位国外的程序员认为 Swift 的语法与 Kotlin 相似,并整理了一些 Swift 和 Kotlin 的对比,下面是一些例子,大家不妨也看看. BASICS Hello World Swift ...
- Swift与Objective-C中的闭包
Swift Code: func makeIncrementor(forIncrement amount: Int) -> (() -> Int,() -> Int) { func ...
- Swift调用Objective C的FrameWork
很多Github的库经过很多年的发展,源码都是OC写的,,所以,用Swift调用OC的库就是开发中难免遇到的的一个问题,本文以AFNetworking为例,讲解如何跨语言调用. 第一步 创建一个空的工 ...
- Swift和Objective C关于字符串的一个小特性
一.Unicode的一个小特性 首先,Unicode规定了许多code point,每一个code point表示一个字符.如\u0033表示字符"3",\u864e表示字符&qu ...
- 作为一个iOS Developer 为什么我不用Swift?
1.开始 在去年这个时候接手了一个iOS项目,项目主用Swift语言进行开发,对于部分第三方Objective C开源库则使用bridge的方式进行调用 当时项目的规模大概是不超过15个页面,功能也比 ...
- Swift 和 C# 的语法比较
昨天看到Jacob Leverich 写了一篇文章 Swift is a lot like Scala 介绍Swift 和 Scala 的语法对比,从这篇文章的确可以看到Swift 的语法和 Scal ...
- iOS开发Swift篇—(二)变量和常量
iOS开发Swift篇—(二)变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3.9倍 ...
- 李洪强iOS开发Swift篇—02_变量和常量
李洪强iOS开发Swift篇—02_变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3. ...
- [转]swift 学习资源 大集合
今天看到了一个swift的学习网站,里面收集了很多学习资源 [转自http://blog.csdn.net/sqc3375177/article/details/29206779] Swift 介绍 ...
随机推荐
- Objective-C ,ios,iphone开发基础:ios数据库(The SQLite Database),使用终端进行简单的数据库操作
SQLite 是一个轻量级的免费关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的内存就够了,可以在(http://www.sqlite.org ...
- [转]T4模版引擎之生成数据库实体类
本文转自:http://www.cnblogs.com/lzrabbit/archive/2012/07/18/2597953.html 在通过T4模版引擎之基础入门 对T4有了初步印象后,我们开始实 ...
- HDU 3533 Escape (BFS + 预处理)
Escape Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- Jersey(1.19.1) - Client API, Uniform Interface Constraint
The Jersey client API is a high-level Java based API for interoperating with RESTful Web services. I ...
- Memcached学习(二)
4.协议简介 Memcached服务与各客户端间通过Tcp链接通讯(也可通过Udp链接). 各客户端间与服务间不需要发送特别的命令关闭链接,只要在不需要的时候直接关闭链接即可.建议客户端与服务间保持长 ...
- ### 学习《C++ Primer》- 9
Part 9: 模板与泛型编程(第16章) // @author: gr // @date: 2016-03-18 // @email: forgerui@gmail.com 1. 模板参数 类型模板 ...
- C#之base关键字
1.base关键字用于从派生类中访问基类的成员. 2.调用基类上已被其他方法重写的方法. 3.指定创建派生类的实例是应调用基类的构造函数. 4.访问基类的公有成员和受保护成员,不能访问私有成员 5在静 ...
- CSS 样式二
CSS文本样式 text-align:设置文本的对齐方式 取值: left 向左对齐 right:向右对齐 center:居中对齐 text-indent:设置文本的首行缩进 例如,字体设为12px, ...
- python 函数应用
#函数的参数就是个变量 #定义函数的时候,使用关键字参数,可以指定默认值 def hello(name='reboot',age=1): return 'hello %s,your age is %s ...
- Mac OS 踩坑指南
前言 其实mac os本身还是很不错的,软硬结合使得其性能.效率.续航得到了很好的优化. 但是毕竟是一个"小众"操作系统,很多在Win上已经用习惯的东西在这里都没有,或者完全不一样 ...