Swift常量:Struct或Enum

时间:2016-07-26 08:57:35

标签: swift struct enums constants

我不确定哪两个更好地定义常量。结构或枚举。每次使用它时都会复制一个结构?当我考虑具有static let常量的结构时,在我看来,它一直都会被复制是没有意义的。但如果它不被复制,那么我所接受的并不重要吗?

结构或枚举的选择有哪些优点?

Francisco say use Struct's.

Ray Wunderlich say use Enum's. But I lack the justification.

5 个答案:

答案 0 :(得分:90)

结构和枚举都有效。作为一个例子,两者

struct PhysicalConstants {
    static let speedOfLight = 299_792_458
    // ...
}

enum PhysicalConstants {
    static let speedOfLight = 299_792_458
    // ...
}

工作并定义静态属性PhysicalConstants.speedOfLight

Re:每次使用它时都会复制一个结构?

structenum都是值类型,因此也适用于枚举。但这是无关的 因为您根本不必创建值: 静态属性(也称为 type 属性)是类型本身的属性,而不是该类型实例的属性。

Re:选择结构或枚举有什么好处?

linked-to article中所述:

  

使用无大小写枚举的优点是它不会被意外地实例化并且作为纯命名空间工作。

所以对于一个结构,

let foo = PhysicalConstants()

创建PhysicalConstants类型的(无用)值,但是 对于无案例枚举,它无法编译:

let foo = PhysicalConstants()
// error: 'PhysicalConstants' cannot be constructed because it has no accessible initializers

答案 1 :(得分:9)

这是一个简短的回答:你的常数是否需要独特?然后使用枚举,强制执行此操作。

想要使用几个不同的常量来包含相同的值(通常用于清晰度)?然后使用一个允许这个的结构。

答案 2 :(得分:7)

两者之间的区别是可以实例化结构,而枚举不能。因此,在大多数只需要使用常量的情况下,最好使用枚举来避免混淆。

例如:

struct Constants {
    static let someValue = "someValue"
}

let _ = Constants()

上面的代码仍然有效。

如果我们使用枚举:

enum Constants {
    static let someValue = "someValue"
}

let _ = Constants() // error

以上代码将无效,因此请避免混淆。

答案 3 :(得分:4)

使用Xcode 7.3.1和Swift 2.2

虽然我同意Martin R,并且Ray Wenderlich风格指南很好地说明了枚举在几乎所有用例中都更好,因为它是纯命名空间,有一个地方使用struct王牌enums

切换语句

让我们从结构版本开始:

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'

通过将static属性转换为返回类型的闭包,有一个伪解决方法。

所以你会改变它:

enum StaticVars {
    static let someString = { return "someString" }
}

switch "someString" {
case StaticVars.someString(): print("Matched StaticVars.someString")
default: print("Didn't match StaticVars.someString")
}

请注意case语句中括号的必要性,因为它现在是一个函数。

缺点是,现在我们已经将它变成了一个函数,它每次被调用时都会被执行。因此,如果它只是一个简单的原始类型,如StringInt,那么这不是很糟糕。它本质上是一个计算属性。如果它是一个需要计算的常量,并且您只想计算一次,请考虑将其计算到不同的属性中并在闭包中返回已计算的值。

您也可以使用私有初始化程序覆盖默认初始值设定项,然后您将获得与无壳枚举相同类型的编译时错误。

struct StaticVars {
    static let someString = "someString"
    private init() {}
}

但是有了这个,你想把结构的声明放在它自己的文件中,因为如果你在同一个文件中声明它,比如一个View Controller类,那个类的文件仍然可以意外地实例化一个无用的StaticVars实例,但是在该类文件之外它可以按预期工作。但这是你的电话。

答案 4 :(得分:3)

Combine框架中,Apple选择了对名称空间使用枚举。

enum Publishers

用作发布者的类型的命名空间。

enum Subscribers

用作订阅者的类型的名称空间。

enum Subscriptions

与订阅相关的符号的命名空间。