Objective-C 开发者对 Swift 亮点的点评

如果这周一你像我一样,正在享受着keynote,很兴奋地要去开始尝试所有新的优美的API。然后当听到讲一门新的语言:Swift时,耳朵都竖起来了!Swift不是对Objective-C的扩展,而是一门全新的语言,这突然震撼到了你。也许你很激动?也许你很开心?也许你没什么想法。

Swift确实已经改变了未来我们开发iOS和Mac上的应用的方式。这篇文章中,我概括了Swift语言的一些亮点,把他们和Objective-C中对应的功能进行了比较。

请注意这并不是一篇Swift入门指南。苹果已经发布了一本讲解Swift的很棒的书,我强烈建议你去阅读一下。取而代之地是,这是一篇对一些值得关注和使用的特别酷的功能的讨论。

类型

Swift给出的第一件重大的事情是类型推断。使用类型推断的语言,程序员不需要使用类型信息给变量作注释。编译器可以从给变量赋的值推断出该变量的类型。例如,编译器可以自动把下面这个值设置为String类型:

// automatically inferred
var name1 = "Matt"
// explicit typing (optional in this case)
var name2:String = "Matt"

连同类型推断一起,Swift还给出了类型安全。在Swift中,编译器(除了少数特殊情况)知道一个对象的完整类型。这使得它能决定怎样来编译代码,因为它有更多的信息随手可用。

这与Objective-C存在明显的不同,Objective-C本质上是非常动态的。在Objective-C中,编译期间不会真正知道对象的类型。部分原因是你可以在运行时给已有的类添加方法,添加一个全新的类,甚至改变一个实例的类型。

让我们来更详细地看一下,考虑到下面的Objective-C语句:

Person *matt = [[Person alloc] initWithName:@"Matt Galloway"];
[matt sayHello];

当编译器看见调用sayHello时,它会检查在头文件中是否声明了这个方法,它会发现类型Person调用了sayHello。如果没有一个Persong对象,就会发生错误,但是这就是编译器所能做的全部了。通常这就足以来捕捉到你引入的bug的第一行了。它会捕捉到输入错误。但是因为动态的特性,编译器不知道sayHello是否将会在运行时改变或者一定会改变。例如,它可以是在协议中的一个可选方法。(还记得这些都可以用respondsToSelector:来检查吗?)。

因为缺乏强类型,所以当在Objective-C中调用方法时编译器基本上不会太多的事来进行优化。处理动态派发的方法叫做objc_msgSend。我相信你在许多的回溯中已经看见了!在该函数中,会查找选择器的实现,然后再跳转。你不能不承认这增加了开销和复杂性。

现在看一下在Swift中相同功能的代码实现:

var matt = Person(name:"Matt Galloway")
matt.sayHello()

在Swift中,编译器知道更多关于类型的信息,这在任何的方法调用中都会起到作用。编译器确切地知道sayHello()在何处被定义。正因如此,通过直接地跳转到实现处而不是必须经过动态派发,编译器可以优化调用的地址。在其他情况下,编译器可以使用虚拟函数表风格派发,这也远低于Objective-C中动态派发的开销。这种类型的派发就是C++中使用的虚函数。

在Swift中编译器更加的有用。它将帮助阻止不确定的类型导致的bug进入你的代码库。通过智能的优化,还能够使你的代码运行的更加快速。

相关推荐