La documentation Swift indique que classes, structs, et enums peuvent tous se conformer aux protocoles, et je peux arriver à un point où ils se conforment tous. Mais je ne peux pas faire en sorte que enum se comporte comme les exemples class et struct:
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
Je n'ai pas trouvé comment obtenir le simpleDescription
à changer suite à l'appel de adjust()
. Mon exemple ne le fera évidemment pas, car getter a une valeur codée en dur, mais comment puis-je définir une valeur pour simpleDescription
tout en restant conforme à ExampleProtocol
?
Ceci est ma tentative:
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
Voici mon point de vue.
Comme il s’agit d’un enum
et non d’un class
, vous devez penser différent (TM): c’est votre description qui doit changer lorsque "l'état" de votre enum
change (comme l'a souligné @ 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
J'espère que ça t'as aidé.
Voici une autre approche, utilisant uniquement les connaissances acquises grâce à la tournée jusqu'à ce 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
Si vous voulez que adjust()
agisse comme une bascule (bien que rien ne permette de penser que c'est le cas), utilisez:
mutating func adjust() {
switch self {
case .Basic:
self = .Adjusted
default:
self = .Basic
}
}
* (Bien qu'il ne mentionne pas explicitement comment spécifier un type de retour et un protocole)
Voici une solution qui ne modifie pas la valeur enum actuelle, mais leurs valeurs d'instance (au cas où cela serait utile à quiconque).
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
Il n'est pas possible de définir des variables sans getter et setter en enum et il est donc impossible d'avoir une variable que vous pouvez modifier.
Vous pouvez vous conformer au protocole mais vous ne pouvez pas avoir le même comportement avec la mutation que dans les classes.
C'est un lien à propos de enum dans Swift.
Les structures et les énumérations sont des types de valeur. Par défaut, les propriétés d'un type de valeur ne peuvent pas être modifiées à partir de ses méthodes d'instance. lien
Ensuite, vous devez utiliser la fonction de mutation.
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
Une autre option est d'ajuster () pour changer de cas comme suit:
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
}
}
Voici la réponse de Jack:
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
}
}
}
Je suis venu avec ça
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
Je pensais que l'objectif est simplement de conserver l'état et d'utiliser une description pour faciliter la lecture de l'état actuel:
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
voici mon 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
Cette expérience m'a également gênée, en raison des exemples précédents SimpleClass et SimpleStructure montrant la propriété simpleDescription étant modifiée en interne, ce qui m'a amené à penser que je devais faire la même chose. Après avoir parcouru les autres réponses postées ici et lu la documentation officielle de Apple Swift 2.1, je trouvai ceci:
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
Notez également que dans les exemples donnés par Apple pour SimpleClass et SimpleStructure avant cette expérience, la description simple est perdue en interne - vous ne pouvez pas récupérer la valeur d'origine (à moins bien sûr de la sauvegarder en dehors de la classe/structure). ; C'est ce qui m'a incité à créer une méthode restore () pour l'exemple SimpleEnum, qui vous permet de basculer entre les valeurs. J'espère que cela est utile à quelqu'un!
Autre variante: utilisation des valeurs associées pour conserver et afficher l'option précédente (de la forme "Sélectionné 1, ajusté à partir de 2, ajusté à partir de 1, ajusté à partir de 2, ajusté à partir de 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"
Ma première contribution ici:
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
Merci pour les autres!