Swift常量:Struct或Enum
我不确定哪个更好定义常量。 结构或枚举。 每次我使用它或不是会复制一个结构体? 当我想到一个带有static let
常量的结构时,在我看来,它总是会被复制,这是毫无意义的。 但是,如果它不会被复制,那么我拿什么都没有关系?
结构或枚举的select有什么优点?
Francisco说使用Struct的。
雷Wunderlich说使用Enum的。 但我缺乏理由。
结构和枚举都起作用。 作为一个例子,两者
struct PhysicalConstants { static let speedOfLight = 299_792_458 // ... }
和
enum PhysicalConstants { static let speedOfLight = 299_792_458 // ... }
工作并定义一个静态属性PhysicalConstants.speedOfLight
。
Re:每当我使用它时,结构都会被复制?
struct
和enum
都是值types,所以也适用于枚举。 但是这里没有什么关系 ,因为根本不需要创build一个值:静态属性(也称为types属性)是types本身的属性,而不是该types的一个实例。
Re:结构或枚举的select有什么优点?
正如链接文章中提到的 :
使用无枚举枚举的优点是它不会意外地被实例化,并且作为一个纯名称空间来工作。
所以对于一个结构,
let foo = PhysicalConstants()
创build一个(无用的) PhysicalConstants
types的值,但对于无例外枚举,则无法编译:
let foo = PhysicalConstants() // error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers
使用Xcode 7.3.1和Swift 2.2
虽然我同意Martin R,Ray Wenderlich风格指南很好地指出,由于枚举是一个纯粹的命名空间,因此几乎在所有用例中枚举都更好,但是有一个地方使用struct
胜过enums
。
切换语句
我们从struct版本开始:
struct StaticVars { static let someString = "someString" } switch "someString" { case StaticVars.someString: print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") }
使用一个结构体,这将匹配和打印Matched StaticVars.someString
。
现在让我们考虑无情的枚举版本(通过只改变关键字struct
为enum
):
enum StaticVars { static let someString = "someString" } switch "someString" { case StaticVars.someString: print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") }
您会注意到,在case StaticVars.someString:
行的switch语句中出现编译时错误。 错误是Enum case 'someString' not found in type 'String'
。
通过将静态属性转换为一个返回types的闭包来实现伪解决方法。
所以你可以这样改变它:
enum StaticVars { static let someString = { return "someString" } } switch "someString" { case StaticVars.someString(): print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") }
注意case语句中括号的需要,因为它现在是一个函数。
缺点是现在我们已经把它变成了一个函数,每次调用它都会被执行。 所以,如果它只是一个简单的基本types如String
或Int
,这并不是那么糟糕。 它本质上是一个计算的属性。 如果它是一个需要计算的常量,并且只需要计算一次,则可以考虑将其计算为不同的属性,并返回已经计算的闭包中的值。
你也可以使用私有的默认初始化方法来覆盖默认的初始化方法,然后你会得到和无情的枚举类似的编译时错误。
struct StaticVars { static let someString = "someString" private init() {} }
但是,有了这个,你会想把结构的声明放在它自己的文件中,因为如果你把它声明在同一个文件中,例如一个View Controller类,那么这个类的文件仍然能够意外地实例化一个无用的StaticVars
实例,但在类的文件之外它将按预期工作。 但这是你的电话。