How to make enum conform to protocol in Swift?

The Swift documentation says that classes, structures, and enums can conform to the protocols, and I can get to the point where they all correspond. But I cannot make an enumeration behave like examples of classes and structures:

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 did not understand how to change simpleDescription as a result of calling adjust() . My example will obviously not do this because the recipient has a hard-coded value, but how can I set the value for simpleDescription still matching ExampleProtocol ?

+62
enums swift swift-protocols
Jun 03 '14 at 9:07
source share
15 answers

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 
+117
Jun 04 '14 at 8:35
source share

Here is my example.

Since this is an enum , not a class , you need to think about something else (TM): this is the description that should change when the "state" of your enum changes (as indicated 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 this helps.

+36
Jun 04 '14 at 10:52
source share

Here's a different approach, using only the knowledge gained from the tour to this 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 adjust() act as a switch (although there is nothing to suggest that it is), use:

 mutating func adjust() { switch self { case .Basic: self = .Adjusted default: self = .Basic } } 

* (Although it does not explicitly indicate how to specify the return type and protocol)

+10
Jun 12 '14 at 16:04
source share

There is a solution here that does not change the current value of the enumeration, but instead its instance value (just in case, this 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 
+7
Jun 13 '14 at 23:16
source share

It is not possible to define variables without getter and setter in enums, and therefore it is not possible to change a variable that you can change.

You can conform to the protocol, but you cannot have the same mutation behavior as in classes.

+4
Jun 03 '14 at 11:07
source share

This is a listing link in swift.

Structures and enumerations are value types. By default, value type properties cannot be changed from its instance methods. link

Then you need to use the mutating function.

 enum ProtocolEnum: ExampleProtocol { case on, off var simpleDescription: String { switch self { case .on: return "Switch is ON" case .off: return "Switch is OFF" } } mutating func adjust() { switch self { case .on: self = off case .off: self = on } } } var c = ProtocolEnum.on c.simpleDescription c.adjust() let cDescription = c.simpleDescription 
+2
Jun 13 '14 at 3:48
source share

Another option is to configure () to switch between cases as follows:

 enum SimpleEnum: ExampleProtocol { case Foo, Bar var simpleDescription: String { get { let value = self == .Foo ? "Foo" : "Bar" return "A simple \(value) enum." } } mutating func adjust() { self = self == .Foo ? .Bar : .Foo } } 
+1
Jun 08 '14 at 12:19
source share

Here's the building to Jack's answer:

 protocol ICanWalk { var description: String { get } mutating func stepIt() } enum TwoStepsForwardThreeStepsBack: Int, ICanWalk { case Base = 0, Step1, Step2 var description: String { return "Step \(self.rawValue)" } mutating func stepIt() { if let nextStep = TwoStepsForwardThreeStepsBack( rawValue: self.rawValue + 1 ) { // going forward. self = nextStep } else { // back to the base. self = TwoStepsForwardThreeStepsBack.Base } } } 
+1
Jan 15 '15 at
source share

I came up with this

 protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } enum Seat: ExampleProtocol { case WindowSeat, MiddleSeat, AisleSeat var simpleDescription : String { switch self { case .WindowSeat: return "Window Seat" case .MiddleSeat: return "Middle Seat" case .AisleSeat: return "Aisle Seat" } } mutating func adjust() { switch self { case .WindowSeat: self = .MiddleSeat case .MiddleSeat: self = . AisleSeat case .AisleSeat: self = .WindowSeat } } } var seat = Seat.MiddleSeat print(seat.simpleDescription) // Middle Seat seat.adjust() print(seat.simpleDescription) // Aisle Seat 
+1
Jun 05 '16 at 19:43
source share

here is my code

 enum SimpleEnum: ExampleProtocol { case Base, Adjusted var simpleDescription: String { get { var description = "A simple enum." switch self { case .Base: return description case .Adjusted: return description + " - [adjusted]" } } } mutating func adjust() { self = SimpleEnum.Adjusted } } var simpleEnum = SimpleEnum.Base simpleEnum.adjust() simpleEnum.simpleDescription 
0
Mar 11 '15 at 7:13
source share

My first contribution is here:

 enum SimpleEnum: ExampleProtocol { case Basic(String), Adjusted(String) init() { self = SimpleEnum.Basic("A simple Enum") } var simpleDescription: String { get { switch self { case let .Basic(string): return string case let .Adjusted(string): return string } } } mutating func adjust() { self = SimpleEnum.Adjusted("full adjusted") } } var c = SimpleEnum() c.adjust() let cDescription = c.simpleDescription 

Thanks for the others!

0
Jun 10 '15 at 10:41
source share

This experiment also threw me off due to previous examples of SimpleClass and SimpleStructure in which the simpleDescription property was internally modified, which made me think that I needed to do the same. After looking at the other answers posted here and reading the official Apple Swift 2.1 documentation, I came up with the following:

 protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } enum SimpleEnum: ExampleProtocol { case Simple case Adjusted var simpleDescription: String { switch self { case .Simple: return "A simple enumeration" case .Adjusted: return "A simple enumeration somewhat changed." } } mutating func adjust() { self = .Adjusted } mutating func restore() { self = .Simple } } var d: SimpleEnum = .Simple d.simpleDescription d.adjust() d.simpleDescription d.restore() d.simpleDescription 

Also note that in the examples provided by Apple for SimpleClass and SimpleStructure before this experiment, a simple description is lost from the inside - you cannot return the original value (unless, of course, you save it outside the class / structure); this prompted me to create a restore () method for the SimpleEnum example, which allows you to switch between values. I hope this is useful to someone!

0
Oct. 15 '15 at 7:19
source share

I thought the goal was just to save the state and use the description to make it easier to read the current state:

 enum SimpleEnum: ExampleProtocol { case Default, Adjusted init() { self = .Default } var simpleDescription: String { get { return "\(self) Value" }} mutating func adjust() { self = .Adjusted } } var simpleEnum = SimpleEnum() simpleEnum.adjust() let adjustedSimple = simpleEnum.simpleDescript 
0
Oct 23 '15 at 11:07
source share

Another option: use related values โ€‹โ€‹to store and display the previous option (in the form "Selected 1, adjusted from 2, adjusted from 1, adjusted from 2, adjusted from 1")

 protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } indirect enum EnumWithDescription: ExampleProtocol { case option1(EnumWithDescription?) case option2(EnumWithDescription?) var simpleDescription: String { return "Selected " + getDescription() } internal func getDescription() -> String { var currentValue: String let previousValue : EnumWithDescription? switch self { case .option1(let previous): currentValue = "1" previousValue = previous case .option2(let previous): currentValue = "2" previousValue = previous } if let adjustedFrom = previousValue?.getDescription() { return "\(currentValue) adjusted from \(adjustedFrom)" } else { return "\(currentValue)" } } mutating func adjust() { switch self { case .option1: self = .option2(self) case .option2: self = .option1(self) } } } var d = EnumWithDescription.option1(nil) d.simpleDescription d.adjust() d.adjust() d.simpleDescription // Output: "Selected 1, adjusted from 2, adjusted from 1, adjusted from 2, adjusted from 1" 
0
Jan 17 '17 at 16:06
source share

how about this

 enum SimpleEnum : ExampleProtocol { case Desc(String) init() { self = Desc("a simple enum") } var simpleDescription:String { get { return (Mirror(reflecting: self).children.first!.value as? String)! } } mutating func adjust() { self = SimpleEnum.Desc(self.desc + " adjusted") } } var e = SimpleEnum() e.simpleDescription # => "a simple enum" e.adjust() e.simpleDescription # => "a simple enum adjusted" 
-one
Oct 25 '15 at 10:33
source share



All Articles