给困惑的 Swift 初学者:struct or class?
Swift是苹果官网精心培育的新世代程序语言,有许多精髓的设计蕴含其中。这些设计一方面让Swift成为更优秀的语言,一方面却也让Swift自学者困惑不已。
最人尽皆知的大概就是optional variable了。虽然掌握optional的精神后会觉得optional是超前卫的想法,但第一次接触Swift的人,大概会被代码中满满的问号与惊叹号吓傻。本文想要讨论的是另一个也令人困惑的议题:struct v.s. class。
一些底层的知识
在其他有struct的语言中,struct一般只能拿来组织逻辑相关的data,使用上没什么疑义。但在Swift中,struct除了可以整理相关的数据,还拥有initializer、拥有method,除了无法被继承以外,和class的使用方式几乎完全一样。这就衍生了另一个问题:在不需要继承的情况下,到底该用struct还是class?
更令人困惑的是,Apple早期的Swift文件推荐开发者优先使用class;一些近期的文件则推荐优先使用struct。
Apple,are you kidding me?所以,我们到底该用哪一个?
在讨论这个议题前,我们需要知道一些底层的知识。
內存分成heap和stack两块。class物件是reference type,会被储存在heap;struct物件是value type,会被存在stack。一般而言,stack的执行效率会比heap好,所以重复的事情,交给struct做,理论上会比class有效率(根据外国人的实测,越新版的Swift,struct性能还是卓越)。
不过“写出优雅、好维护的”代码大部分的时候比写出“高效能的代码”重要。struct执行效率较高绝对不是Apple在新文件中推广struct的原因。
Protocol-Oriented Programming
Object-Oriented Programming(OOP)是近年软件开发的主流设计模式,但在2015 WWDC,Apple对这个称霸数十载的设计模式提出挑战。
Apple认为,在OOP的构架中,假如super class定义过于狭窄,能继承于此super class的sub class就会较少;为了让super class较「通用」、能被较多sub classes继承,开发者往往需要在super class中加入许多properties,但这些properties却未必是每个sub class都需要的。于是,OOP为主的项目容易庞杂、且代码容易缺乏弹性。
于是,Apple提出Protocol Oriented Programming(POP),主张应该用protocol当作设计程序构架的基础,以解决OOP容易庞杂、缺乏弹性的缺点。
对POP细节有兴趣的读者可以自行观看WWDC视频。总之,class能够被继承的特性是OOP的核心,但class有效率较差、数据容易被误改(因为reference type的特性)的问题。假如改用OOP以外的设计模式(例如POP),我们就不必常常依赖class的继承特性,自然就可以优先使用效率较佳、数据较「安全」(因为value type的特性)的struct。
归根究柢,Apple在近期的文间开始推广struct,主要还是因为Apple在推广POP,在POP下,使用struct大部分的时候比使用class更明智。
小结
class和struct在Swift中非常相似,一般情况下,我们习惯使用OOP,所以会优先(且必须)使用class。
但Apple去年开始推广POP,在这个新的设计模式下,我们对class能够继承的特性不再那么倚赖,所以在大部分的情境下,使用优点较多的struct就变比较合理的选择。
不过OOP毕竟还是当前主流,Apple自己也说OOP还是有优点和必要,POP无法完全取代OOP。
到底要用class还struct,还是需要根据个别情况斟酌。
可以确定的是,在swift中,称霸数十载的class不再是需要使用物件时的唯一选择了。