How to make an enum conform to a protocol in Swift?
Solution 1
This is my attempt:
protocol ExampleProtocol {
var simpleDescription: String { get }
mutating func adjust()
}
enum ExampleEnum : ExampleProtocol {
case Base, Adjusted
var simpleDescription: String {
return self.getDescription()
}
func getDescription() -> String {
switch self {
case .Base:
return "A simple description of enum"
case .Adjusted:
return "Adjusted description of enum"
}
}
mutating func adjust() {
self = ExampleEnum.Adjusted
}
}
var c = ExampleEnum.Base
c.adjust()
let cDescription = c.simpleDescription
Solution 2
Here is my take at it.
As this is an enum
and not a class
, you have to think different(TM): it is your description that has to change when the "state" of your enum
changes (as pointed out by @hu-qiang).
enum SimpleEnumeration: ExampleProtocol {
case Basic, Adjusted
var description: String {
switch self {
case .Basic:
return "A simple Enumeration"
case .Adjusted:
return "A simple Enumeration [adjusted]"
}
}
mutating func adjust() {
self = .Adjusted
}
}
var c = SimpleEnumeration.Basic
c.description
c.adjust()
c.description
Hope that helps.
Solution 3
Here's another approach, using only the knowledge gained from the tour until that point*
enum SimpleEnumeration: String, ExampleProtocol {
case Basic = "A simple enumeration", Adjusted = "A simple enumeration (adjusted)"
var simpleDescription: String {
get {
return self.toRaw()
}
}
mutating func adjust() {
self = .Adjusted
}
}
var c = SimpleEnumeration.Basic
c.adjust()
let cDescription = c.simpleDescription
If you want to have adjust()
act as a toggle (although there's nothing to suggest this is the case), use:
mutating func adjust() {
switch self {
case .Basic:
self = .Adjusted
default:
self = .Basic
}
}
*(Although it doesn't explicitly mention how to specify a return type and a protocol)
Solution 4
Here's a solution that doesn't change the current enum value, but their instance values instead (just in case it is useful to anyone).
enum ProtoEnumeration : ExampleProtocol {
case One(String)
case Two(String)
var simpleDescription: String {
get {
switch self {
case let .One(desc):
return desc
case let .Two(desc):
return desc
}
}
}
mutating func adjust() {
switch self {
case let .One(desc):
self = .One(desc + ", adjusted 1")
case let .Two(desc):
self = .Two(desc + ", adjusted 2")
}
}
}
var p = ProtoEnumeration.One("test")
p.simpleDescription
p.adjust()
p.simpleDescription
Solution 5
It is not possible to define variables without getter and setter in enums and therefore it is impossible to have a variable that you can modify.
You can conform to the protocol but you cannot have same behavior with mutating as in classes.
Related videos on Youtube
Adrian Harris Crowne
Updated on June 03, 2020Comments
-
Adrian Harris Crowne about 4 years
Swift documentation says that classes, structs, and enums can all conform to protocols, and I can get to a point where they all conform. But I can't get the enum to behave quite like the class and struct examples:
protocol ExampleProtocol { var simpleDescription: String { get set } mutating func adjust() } class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 69105 func adjust() { simpleDescription += " Now 100% adjusted." } } var a = SimpleClass() a.adjust() let aDescription = a.simpleDescription struct SimpleStructure: ExampleProtocol { var simpleDescription: String = "A simple structure" mutating func adjust() { simpleDescription += " (adjusted)" } } var b = SimpleStructure() b.adjust() let bDescription = b.simpleDescription enum SimpleEnum: ExampleProtocol { case Base var simpleDescription: String { get { return "A Simple Enum" } set { newValue } } mutating func adjust() { self.simpleDescription += ", adjusted" } } var c = SimpleEnum.Base c.adjust() let cDescription = c.simpleDescription
I haven't figured out how to get the
simpleDescription
to change as a result of callingadjust()
. My example obviously won't do that because the getter has a value hard-coded, but how can I set a value for thesimpleDescription
while still conforming to theExampleProtocol
? -
Adrian Harris Crowne about 10 yearsAwesome! I had that idea of creating an adjusted state, but it didn't occur to me that I could change to .Adjusted in the adjust method. Thanks!
-
Admin about 10 yearsi agree with your take on the enum itself, and with the code you provided. nice.
-
jpittman about 10 yearsExcellent pointer. Was a bit stuck on this one. One question though: Any reason you added the return value of Void to the adjust function?
-
Angelo about 10 years@jpittman because the
adjust
function returnsVoid
in theExampleProtocol
, it's the same as just usingmutating func adjust()
. If you wantadjust
to have a return type, you can change the protocol to: gist.github.com/anjerodesu/e1bf640576a3b6fa415f -
DiogoNeves about 10 yearsExtra points for whoever finds a way to avoid all those switches. Something along the lines of this fictitious copy
self = copy(self, self.desc + ", asdfasdf")
-
Justin Levi Winter over 9 yearsI think this approach is probably the best one of the bunch. Quick update is that the simpleDescription should return self.rawValue
-
Ricardo Sanchez-Saez over 9 yearsThis answer is nicer and more succinct than the accepted one.
-
Shaolo over 9 yearsJust a side note that you can remove the SimpleEnumeration.Adjusted and replace with just ".Adjusted". If the name of the enumeration ever changes then it's one less thing to refactor.
-
Robert about 9 yearsCould you also add an explanation?
-
Indra Rusmita about 9 years@Robert it should be self explained like others but the different are that I am using init method in enum and have default basic enum. so you'll see that when you create enum object like in structure and class example in Swift playground.
-
John Doe over 7 yearsCould not edit the answer to correct the syntax error, it is missing a dot, should be
case .Base:
-
Arjun Kalidas almost 7 yearsYeah, this is better. Thanks.
-
barry almost 7 yearsThis doesn't conform to the given protocol though