Wie kann man eine Aufzählung an ein Protokoll in Swift anpassen?

93

Die schnelle Dokumentation besagt, dass Klassen , Strukturen und Aufzählungen alle Protokollen entsprechen können, und ich kann zu einem Punkt gelangen, an dem sie alle übereinstimmen. Aber ich kann die Aufzählung nicht dazu bringen , sich ganz wie die Klassen- und Strukturbeispiele zu verhalten :

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

Ich habe nicht herausgefunden, wie ich das simpleDescriptiondurch einen Anruf ändern kann adjust(). Mein Beispiel wird das natürlich nicht tun, weil der Getter einen fest codierten Wert hat, aber wie kann ich einen Wert für die festlegen, simpleDescriptionwährend er noch dem entspricht ExampleProtocol?

Adrian Harris Crowne
quelle

Antworten:

154

Das ist mein Versuch:

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
Hu Qiang
quelle
Dies erfüllt das Protokoll, ist aber dennoch als Aufzählung sinnvoll. Gute Arbeit!
David James
1
Genial! Ich hatte die Idee, einen angepassten Status zu erstellen, aber mir fiel nicht ein, dass ich in der Anpassungsmethode zu .Adjusted wechseln könnte. Vielen Dank!
Adrian Harris Crowne
Hervorragender Zeiger. War ein bisschen festgefahren. Eine Frage: Gibt es einen Grund, warum Sie der Anpassungsfunktion den Rückgabewert von Void hinzugefügt haben?
Jpittman
@jpittman, da die adjustFunktion Voidin der zurückgegeben wird ExampleProtocol, ist es dasselbe wie nur mit mutating func adjust(). Wenn Sie adjusteinen Rückgabetyp haben möchten , können Sie das Protokoll ändern in: gist.github.com/anjerodesu/e1bf640576a3b6fa415f
Angelo
1
Konnte die Antwort nicht bearbeiten, um den Syntaxfehler zu korrigieren, es fehlt ein Punkt, sollte seincase .Base:
John Doe
44

Hier ist meine Einstellung dazu.

Da dies ein enumund kein ist class, müssen Sie anders denken (TM) : Es ist Ihre Beschreibung, die sich ändern muss, wenn sich der "Zustand" Ihrer enumÄnderungen ändert (wie von @ hu-qiang hervorgehoben).

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

Hoffentlich hilft das.

Zedenem
quelle
Ich stimme Ihrer Meinung zur Aufzählung selbst und dem von Ihnen angegebenen Code zu. nett.
4
Diese Antwort ist schöner und prägnanter als die akzeptierte.
Ricardo Sanchez-Saez
2
Nur eine Randnotiz, dass Sie die SimpleEnumeration.Adjusted entfernen und durch nur ".Adjusted" ersetzen können. Wenn sich der Name der Aufzählung jemals ändert, ist eine Umgestaltung weniger erforderlich.
Shaolo
Ja, das ist besser. Vielen Dank.
Arjun Kalidas
Dies entspricht jedoch nicht dem angegebenen Protokoll
Barry
11

Hier ist ein anderer Ansatz, bei dem nur das Wissen verwendet wird, das bis zu diesem Zeitpunkt aus der Tour gewonnen wurde *

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

Wenn Sie adjust()als Umschalter fungieren möchten (obwohl nichts darauf hindeutet, dass dies der Fall ist), verwenden Sie:

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

* (Obwohl nicht ausdrücklich erwähnt wird, wie ein Rückgabetyp und ein Protokoll angegeben werden)

Jack James
quelle
2
Ich denke, dieser Ansatz ist wahrscheinlich der beste. Schnelles Update ist, dass die simpleDescription self.rawValue
Justin Levi Winter
7

Hier ist eine Lösung, die nicht den aktuellen Aufzählungswert ändert, sondern deren Instanzwerte (nur für den Fall, dass dies für irgendjemanden nützlich ist).

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
DiogoNeves
quelle
Zusätzliche Punkte für alle, die einen Weg finden, all diese Schalter zu umgehen. Etwas in der Art dieser fiktiven Kopieself = copy(self, self.desc + ", asdfasdf")
DiogoNeves
4

Es ist nicht möglich, Variablen ohne Getter und Setter in Enums zu definieren, und daher ist es unmöglich, eine Variable zu haben, die Sie ändern können.

Sie können sich an das Protokoll anpassen, aber Sie können sich beim Mutieren nicht wie in Klassen verhalten.

Tomáš Linhart
quelle
2

Es ist ein Link über Enum in Swift.

Strukturen und Aufzählungen sind Werttypen. Standardmäßig können die Eigenschaften eines Wertetyps nicht innerhalb seiner Instanzmethoden geändert werden. Verknüpfung

Dann müssen Sie die Mutationsfunktion verwenden.

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
Jeff Gu Kang
quelle
1

Eine weitere Option ist, dass adjust () wie folgt zwischen den Fällen wechselt:

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
    }
}
Endersstocker
quelle
1

Hier baut auf Jacks Antwort auf:

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
        }
    }
}
Alex Akhtyrskiy
quelle
1

Ich habe mir das ausgedacht

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
Groot
quelle
0

Hier ist mein 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
NOCKEN
quelle
0

Mein erster Beitrag hier:

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

Danke für andere!

Indra Rusmita
quelle
1
Könnten Sie auch eine Erklärung hinzufügen?
Robert
@ Robert sollte es wie andere selbst erklärt werden, aber die anderen sind, dass ich die init-Methode in enum verwende und die Standard-Grundaufzählung habe. Sie werden das also sehen, wenn Sie ein Enum-Objekt wie im Struktur- und Klassenbeispiel auf dem Swift-Spielplatz erstellen.
Indra Rusmita
0

Dieses Experiment hat mich auch umgehauen, da die vorherigen SimpleClass- und SimpleStructure-Beispiele zeigten, dass die Eigenschaft simpleDescription intern geändert wurde, was mich zu der Annahme veranlasste, dass ich dasselbe tun musste. Nachdem ich mir die anderen hier veröffentlichten Antworten angesehen und die offizielle Dokumentation zu Apple Swift 2.1 gelesen hatte, kam ich zu folgendem Ergebnis:

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

Beachten Sie auch, dass in den Beispielen von Apple für SimpleClass und SimpleStructure vor diesem Experiment die einfache Beschreibung intern verloren geht - Sie können den ursprünglichen Wert nicht zurückerhalten (es sei denn, Sie speichern ihn natürlich außerhalb der Klasse / Struktur). Aus diesem Grund habe ich eine restore () -Methode für das SimpleEnum-Beispiel erstellt, mit der Sie zwischen den Werten hin und her wechseln können. Hoffe das ist nützlich für jemanden!

William L. Marr III
quelle
0

Ich dachte, dass das Ziel einfach darin besteht, den Status beizubehalten und eine Beschreibung zu verwenden, um den aktuellen Status leichter lesbar zu machen:

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
Johan
quelle
0

Eine weitere Variante: Verwenden der zugehörigen Werte zum Halten und Anzeigen der vorherigen Option (in der Form "Ausgewählte 1, angepasst von 2, angepasst von 1, angepasst von 2, angepasst von 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"
nkalvi
quelle
-1

Wie wäre es damit

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"
michex
quelle