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 calling adjust()
. My example obviously won't do that because the getter has a value hard-coded, but how can I set a value for the simpleDescription
while still conforming to the ExampleProtocol
?
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
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.
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)
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
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.
It is a link about enum in swift.
Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods. link
Then, you have to use 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
Another option is for adjust() to flip 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
}
}
Here's building on 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
}
}
}
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
here's 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
My first contribution 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 others!
This experiment threw me off too, due to the previous SimpleClass and SimpleStructure examples showing the property simpleDescription being modified internally, which caused me to think that I needed to do the same thing. After looking over the other answers posted here and reading the official Apple Swift 2.1 documentation, I came up with this:
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 notice that in the examples given by Apple for SimpleClass and SimpleStructure prior to this experiment, the simple description is lost internally - you cannot get the original value back (unless of course you save it outside of the class/structure); this is what prompted me to create a restore() method for the SimpleEnum example, which allows you to toggle it back and forth between values. Hope this is useful to someone!
I was thinking that the goal is simply to retain state and use a description to make the current state easier to read:
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
Another variation: Using associated values to hold and display previous option (of 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"
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"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.