Dokumentacja Swift mówi, że wszystkie klasy , struktury i wyliczenia mogą być zgodne z protokołami i mogę dojść do punktu, w którym wszystkie są zgodne. Ale nie mogę sprawić, by wyliczenie zachowywało się tak, jak przykłady klas i struktur :
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
Nie wymyśliłem, jak sprawić, simpleDescription
by zmienił się w wyniku rozmowy adjust()
. Mój przykład oczywiście tego nie zrobi, ponieważ metoda pobierająca ma wartość zakodowaną na stałe, ale jak mogę ustawić wartość dla, simpleDescription
jednocześnie zachowując zgodność z ExampleProtocol
?
swift
enums
swift-protocols
Adrian Harris Crowne
źródło
źródło
adjust
funkcja zwracaVoid
wExampleProtocol
, to to samo, co samo użyciemutating func adjust()
. Jeśli chceszadjust
mieć zwracany typ, możesz zmienić protokół na: gist.github.com/anjerodesu/e1bf640576a3b6fa415fcase .Base:
Oto moje spojrzenie na to.
Ponieważ jest to
enum
a nie aclass
, musisz myśleć inaczej (TM) : to twój opis musi się zmienić, gdy „stan” twoichenum
zmian (jak wskazał @ 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
Mam nadzieję, że to pomoże.
źródło
Oto inne podejście, wykorzystujące tylko wiedzę zdobytą podczas wycieczki do tego momentu *
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
Jeśli chcesz, aby
adjust()
działał jako przełącznik (chociaż nic nie sugeruje, że tak jest), użyj:mutating func adjust() { switch self { case .Basic: self = .Adjusted default: self = .Basic } }
* (Chociaż nie wspomniano wyraźnie, jak określić typ zwrotu i protokół)
źródło
Oto rozwiązanie, które nie zmienia bieżącej wartości wyliczenia, ale zamiast tego wartości ich wystąpienia (na wypadek, gdyby było przydatne dla każdego).
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
źródło
self = copy(self, self.desc + ", asdfasdf")
Nie jest możliwe zdefiniowanie zmiennych bez metody pobierającej i ustawiającej w wyliczeniach, dlatego nie można mieć zmiennej, którą można modyfikować.
Możesz dostosować się do protokołu, ale nie możesz mieć takiego samego zachowania z mutacją jak w klasach.
źródło
To jest łącze o enum in swift.
Struktury i wyliczenia są typami wartości. Domyślnie właściwości typu wartości nie mogą być modyfikowane z poziomu jego metod instancji. połączyć
Następnie musisz użyć funkcji mutacji.
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
źródło
Inną opcją jest funkcja Adjust (), aby przełączać się między przypadkami w następujący sposób:
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 } }
źródło
Oto odpowiedź Jacka:
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 } } }
źródło
Wymyśliłem to
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
źródło
oto mój kod
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
źródło
Mój pierwszy wkład tutaj:
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
Dzięki za innych!
źródło
Ten eksperyment również mnie odrzucił, ponieważ poprzednie przykłady SimpleClass i SimpleStructure pokazały wewnętrzną modyfikację właściwości simpleDescription, co spowodowało, że pomyślałem, że muszę zrobić to samo. Po przejrzeniu innych odpowiedzi zamieszczonych tutaj i przeczytaniu oficjalnej dokumentacji Apple Swift 2.1 wymyśliłem to:
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
Zauważ również, że w przykładach podanych przez Apple dla SimpleClass i SimpleStructure przed tym eksperymentem, prosty opis jest tracony wewnętrznie - nie możesz odzyskać pierwotnej wartości (chyba że zapiszesz ją poza klasą / strukturą); to właśnie skłoniło mnie do utworzenia metody restore () dla przykładu SimpleEnum, która pozwala na przełączanie się między wartościami. Mam nadzieję, że to komuś się przyda!
źródło
Myślałem, że celem jest po prostu zachowanie stanu i użycie opisu, aby uczynić bieżący stan łatwiejszym do odczytania:
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
źródło
Inny wariant: użycie powiązanych wartości do zatrzymania i wyświetlenia poprzedniej opcji (w postaci „Wybrano 1, skorygowano z 2, skorygowano od 1, skorygowano z 2, skorygowano od 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"
źródło
co powiesz na to
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"
źródło