Reputation: 923
suppose I have
enum Example {
case one(string: String)
case two(string: String)
}
and now I have
let x = Example.one(string: "Hello")
The question:
let y = ?
how do I create another instance of the same enum in e
, so that I end up with y == .one("World")
)
Upvotes: 2
Views: 2533
Reputation: 73236
The types of enum
cases with associated values are closures with arguments corresponding to the type of the associated values, and with a return corresponding to the type of the enum
(with the value of the return being the specific case
). I.e., for your example above, the type of Example.one
as well as Example.two
is (String) -> Example
, where the closures expressed by these two cases yield different results; instances of .one(...)
and .two(...)
, respectively.
Hence, instead of writing your own method to "clone" a given case, you could simply have a computed property which returns the already existing closures Example.one
and Example.two
(if self is one
or two
, respectively), which can subsequently be invoked upon a String
argument to construct a new Example
instance (with value .one
or .two
; along with the supplied associated String
value).
E.g.:
enum Example {
case one(string: String) // type: (String) -> Example
case two(string: String) // type: (String) -> Example
var caseClosure: (String) -> Example {
switch self {
case .one: return Example.one
case .two: return Example.two
}
}
}
let x = Example.one(string: "Hello") // .one("Hello")
let y = x.caseClosure("World") // .one("World")
However, since all the cases in your example are closures of the same type, namely (String) -> Example
(i.e. have the same number and type(s) of associated values), you might as well, as already proposed in a comment by @Hamish, wrap an enum
with no associated values in a struct
along with the always-String
"associated value" a separate member of the struct
. E.g. expanding Hamish's example with some initializers:
struct S {
enum E {
case one
case two
}
var e: E
var string: String // Since "associated value" is always the same type
init(_ e: E, string: String) {
self.e = e
self.string = string
}
init(from s: S, string: String) {
self.e = s.e
self.string = string
}
}
let x = S(.one, string: "Hello")
let y = S(from: x, string: "World")
let z = S(x.e, string: "World")
Upvotes: 1
Reputation: 2854
You do that by calling the Initializer exactly like you did for x
:
enum Example {
case one(string: String)
case two(string: String)
}
let x = Example.one(string: "Hello")
print(x) // Prints one("Hello")
let y = Example.one(string: "World")
print(y) // Prints one("World")
Also, The ,
in your enum declaration is wrong and has to be removed.
UPDATE:
The comment explained the question in more detail, so here is my updated answer:
An elegant way to solve this is to use a function on the original enum type Example
.
enum Example {
case one(string: String)
case two(string: String)
func cloneWith(string: String) -> Example {
switch self {
case .one:
return .one(string: string)
case .two:
return .two(string: string)
}
}
}
let x = Example.one(string: "Hello")
print(x) // Prints one("Hello")
let y = x.cloneWith(string: "World")
print(y) // Prints one("World")
Upvotes: 1