Swift constants: Struct or Enum

匿名 (未验证) 提交于 2019-12-03 01:49:02

问题:

I'm not sure which of both are better to define constants. A struct or a enum. A struct will be copied every time i use it or not? When i think about a struct with static let constants it makes no sense that it will copied all the time, in my opinion. But if it won't copied then it doesn't matter what I take?

What advantages does the choice of a struct or enum?

Francisco say use Struct's.

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

回答1:

Both structs and enumerations work. As an example, both

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

and

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

work and define a static property PhysicalConstants.speedOfLight.

Re: A struct will be copied every time i use it or not?

Both struct and enum are value types so that would apply to enumerations as well. But that is irrelevant here because you don't have to create a value at all: Static properties (also called type properties) are properties of the type itself, not of an instance of that type.

Re: What advantages has the choice of a struct or enum?

As mentioned in the linked-to article:

The advantage of using a case-less enumeration is that it can't accidentally be instantiated and works as a pure namespace.

So for a structure,

let foo = PhysicalConstants() 

creates a (useless) value of type PhysicalConstants, but for a case-less enumeration it fails to compile:

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


回答2:

Using Xcode 7.3.1 and Swift 2.2

While I agree with Martin R, and the Ray Wenderlich style guide makes a good point that enums are better in almost all use cases due to it being a pure namespace, there is one place where using a struct trumps enums.

Switch statements

Let's start with the struct version:

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

Using a struct, this will match and print out Matched StaticVars.someString.

Now lets consider the caseless enum version (by only changing the keyword struct to enum):

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

You'll notice that you get a compile time error in the switch statement on the case StaticVars.someString: line. The error is Enum case 'someString' not found in type 'String'.

There's a pseudo-workaround by converting the static property to a closure that returns the type instead.

So you would change it like this:

enum StaticVars {     static let someString = { return "someString" } }  switch "someString" { case StaticVars.someString(): print("Matched StaticVars.someString") default: print("Didn't match StaticVars.someString") } 

Note the need for parentheses in the case statement because it's now a function.

The downside is that now that we've made it a function, it gets executed every time it's invoked. So if it's just a simple primitive type like String or Int, this isn't so bad. It's essentially a computed property. If it's a constant that needs to be computed and you only want to compute it once, consider computing it into a different property and returning that already computed value in the closure.

You could also override the default initializer with a private one, and then you'll get the same kind of compile time error goodness as with the caseless enum.

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

But with this, you'd want to put the declaration of the struct in its own file, because if you declared it in the same file as, say, a View Controller class, that class's file would still be able to accidentally instantiate a useless instance of StaticVars, but outside the class's file it would work as intended. But it's your call.



回答3:

Here's a short answer: Do your constants need to be unique? Then use an enum, which enforces this.

Want to use several different constants to contain the same value (often useful for clarity)? Then use a struct, which allows this.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!