В документации Swift говорится, что классы , структуры и перечисления могут соответствовать протоколам, и я могу добраться до точки, где все они соответствуют. Но я не могу заставить перечисление вести себя так же, как примеры классов и структур :
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
Я не придумал, как заставить simpleDescription
измениться в результате звонка adjust()
. В моем примере этого явно не будет, потому что у геттера жестко запрограммировано значение, но как я могу установить значение, simpleDescription
пока оно все еще соответствует ExampleProtocol
?
swift
enums
swift-protocols
Адриан Харрис Краун
источник
источник
adjust
функция возвращаетсяVoid
вExampleProtocol
, это то же самое, что просто использоватьmutating func adjust()
. Если вы хотитеadjust
иметь возвращаемый тип, вы можете изменить протокол на: gist.github.com/anjerodesu/e1bf640576a3b6fa415fcase .Base:
Вот мой взгляд на это.
Поскольку это,
enum
а не aclass
, вы должны думать иначе (TM) : это ваше описание, которое должно измениться, когда «состояние» вашихenum
изменений (как указано @ 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
Надеюсь, это поможет.
источник
Вот еще один подход, использующий только знания, полученные в ходе тура до этого момента *
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
Если вы хотите, чтобы он
adjust()
действовал как переключатель (хотя нет никаких оснований предполагать, что это так), используйте:mutating func adjust() { switch self { case .Basic: self = .Adjusted default: self = .Basic } }
* (Хотя здесь явно не упоминается, как указать тип возвращаемого значения и протокол)
источник
Вот решение, которое не изменяет текущее значение перечисления, а вместо этого значения их экземпляров (на всякий случай, это полезно для всех).
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
источник
self = copy(self, self.desc + ", asdfasdf")
Невозможно определить переменные без геттера и сеттера в перечислениях, и поэтому невозможно иметь переменную, которую вы можете изменить.
Вы можете соответствовать протоколу, но у вас не может быть такого же поведения с изменением, как в классах.
источник
Это ссылка на enum in swift.
Структуры и перечисления - это типы значений. По умолчанию свойства типа значения не могут быть изменены из методов его экземпляра. ссылка на сайт
Затем вам нужно использовать функцию мутации.
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
источник
Другой вариант - для adjust () переключаться между случаями следующим образом:
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 } }
источник
Основываясь на ответе Джека:
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 } } }
источник
Я придумал это
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
источник
вот мой код
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
источник
Мой первый вклад здесь:
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
Спасибо другим!
источник
Этот эксперимент тоже сбил меня с толку, поскольку в предыдущих примерах SimpleClass и SimpleStructure было показано, что свойство simpleDescription изменено внутри, что заставило меня подумать, что мне нужно сделать то же самое. После просмотра других ответов, размещенных здесь, и чтения официальной документации Apple Swift 2.1, я пришел к следующему:
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
Также обратите внимание, что в примерах, данных Apple для SimpleClass и SimpleStructure до этого эксперимента, простое описание потеряно внутри - вы не можете вернуть исходное значение (если, конечно, вы не сохраните его вне класса / структуры); именно это побудило меня создать метод restore () для примера SimpleEnum, который позволяет переключать его между значениями. Надеюсь, это кому-то будет полезно!
источник
Я думал, что цель - просто сохранить состояние и использовать описание, чтобы его было легче читать:
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
источник
Другой вариант: использование связанных значений для удержания и отображения предыдущего параметра (вида «Выбрано 1, настроено из 2, настроено из 1, настроено из 2, настроено из 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"
источник
как насчет этого
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"
источник