Reputation: 16715
Today someone commented on this code and suggested it would be better in an enum
:
typealias PolicyType = (filename: String, text: String)
struct Policy {
static let first = PolicyType(filename: "firstFile.txt", text: "text in first file")
static let second = PolicyType(filename: "secondFile.txt", text: "text in second file")
static let third = PolicyType(filename: "thirdFile.txt", text: "text in third file")
}
let thirdPolicyText = Policy.third.text
Is there a more memory efficient, maintainable way to do this with an enum? My primary objective is maintainability.
Below is what I've come up with:
enum Policy: RawRepresentable {
case one
case two
case three
var rawValue: (filename: String, text: String) {
switch self {
case .one:
return ("1", "policy 1 text")
case .two:
return ("2", "policy 2 text")
case .three:
return ("3", "policy 3 text")
}
}
init?(rawValue: (filename: String, text: String)) {
switch rawValue {
case ("1", "policy 1 text"):
self = .one
case ("2", "policy 2 text"):
self = .two
case ("3", "policy 3 text"):
self = .three
default:
return nil
}
}
}
At this point, I've figured out how to achieve similar functionality with a struct
and an enum
. The enum
seems like a lot more maintenance if someone goes back to update it and it's more error prone. Paul Hegarty says line that won't crash is the line you don't write and the enum
route looks and feels cumbersome.
Is there a memory advantage to going the enum
route versus a struct
?
When I'm done, I'd like to be able to pass around a Policy as a parameter, like so:
func test(for policy: Policy) {
print(policy.rawValue.filename)
print(policy.rawValue.text)
}
test(for: Policy.first)
Upvotes: 2
Views: 306
Reputation: 32782
The only improvement by using an enum that I can think of is just simply replacing the struct
keyword by an enum
one:
enum Policy {
static let first = PolicyType(filename: "firstFile.txt", text: "text in first file")
static let second = PolicyType(filename: "secondFile.txt", text: "text in second file")
static let third = PolicyType(filename: "thirdFile.txt", text: "text in third file")
}
Enums with no cases are impossible to instantiate, this way the developers can use only the defined static policy types.
A function like this:
func cantBeCalled(policy: Policy) { }
can't be called from your code since it's impossible to construct (allocate) a Policy
.
Still, I'd keep the struct, and redesign everything into a single type:
struct Policy {
static let first = Policy(filename: "firstFile.txt", text: "text in first file")
static let second = Policy(filename: "secondFile.txt", text: "text in second file")
static let third = Policy(filename: "thirdFile.txt", text: "text in third file")
public let filename: String
public let text: String
private init(filename: String, text: String) {
self.filename = filename
self.text = text
}
}
A struct maps better over your problem domain, as you need a container that will hold the two properties. Tuples are not good at scaling when the number of details grows, and are also harder to manipulate (they can't conform to protocols for example).
This new struct design has the same advantages like the above enum: can't construct policies "by hand", only a set of predefined policies are available. And comes with more benefits: only one type, better semantics for the container, ability to use protocols on the Policy
type, no ambiguous accesses to the properties (the members of a labeled tuple can be accessed either via the label, or via the index).
Upvotes: 1
Reputation: 3597
Here's a possibility. It's a little lengthy, but it is Swifty:
enum Policy {
case one, two, three
var filename: String {
switch self {
case .one: return "Policy 1 name"
case .two: return "Policy 2 name"
case .three: return "Policy 3 name"
}
}
var text: String {
switch self {
case .one: return "Policy 1 text"
case .two: return "Policy 2 text"
case .three: return "Policy 3 text"
}
}
}
The problem with Swift enums at the moment is that they are limited to RawValues. I recently encountered a similar situation as you, and I too tried to use an enum instead of a struct. I even experimented with a named tuple. But, I ended up using a struct.
Upvotes: 3