열거 형이 Swift의 프로토콜을 준수하도록 만드는 방법은 무엇입니까?


93

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?

답변:


155

이것은 내 시도입니다.

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

이것은 프로토콜을 만족하지만 여전히 열거 형으로 의미가 있습니다. 잘 했어!
David James

1
대박! 조정 된 상태를 만드는 아이디어가 있었지만 adjust 메서드에서 .Adjusted로 변경할 수 있다는 생각이 들지 않았습니다. 감사!
Adrian Harris Crowne

훌륭한 포인터. 이것에 약간 붙어있었습니다. 하지만 한 가지 질문 : 조정 기능에 Void의 반환 값을 추가 한 이유는 무엇입니까?
jpittman

@jpittman adjust함수가 Void에서 반환 되기 때문에을 ExampleProtocol사용하는 것과 동일 mutating func adjust()합니다. adjust반환 유형 을 원하면 프로토콜을 gist.github.com/anjerodesu/e1bf640576a3b6fa415f
Angelo

1
구문 오류를 정정 할 수있는 대답을 편집 할 수 없습니다,이 점을 누락해야한다case .Base:
홍길동

44

여기에 내 의견이 있습니다.

이것은 enum이고 아니므로 다르게 생각class 해야합니다 (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

도움이 되었기를 바랍니다.


나는 열거 형 자체에 대한 귀하의 견해와 귀하가 제공 한 코드에 동의합니다. 좋은.

4
이 답변은 받아 들여지는 답변보다 더 좋고 간결합니다.
Ricardo Sanchez-Saez 2014

2
SimpleEnumeration.Adjusted를 제거하고 ".Adjusted"로 바꿀 수 있다는 참고 사항입니다. 열거 형의 이름이 변경되면 리팩터링하는 것이 하나 적습니다.
Shaolo

네, 더 좋습니다. 감사.
Arjun Kalidas

이것은 주어진 프로토콜을 따르지 않습니다
barry

11

그 시점까지 투어에서 얻은 지식만을 사용하는 또 다른 접근 방식이 있습니다. *

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
    }
}

* (반환 유형 프로토콜 을 지정하는 방법을 명시 적으로 언급하지는 않지만 )


2
이 접근 방식이 아마도 가장 좋은 방법이라고 생각합니다. 빠른 업데이트는 simpleDescription이 self.rawValue를 반환해야한다는 것입니다.
Justin Levi Winter

7

다음은 현재 열거 형 값을 변경하지 않고 대신 인스턴스 값을 변경하는 솔루션입니다 (누구에게나 유용 할 경우).

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")
DiogoNeves

4

enum에서 getter 및 setter없이 변수를 정의 할 수 없으므로 수정할 수있는 변수를 가질 수 없습니다.

프로토콜을 따를 수는 있지만 클래스에서와 같이 mutating과 동일한 동작을 할 수는 없습니다.


2

그것은이다 링크 신속의 열거에 대해.

구조와 열거는 값 유형입니다. 기본적으로 값 유형의 속성은 인스턴스 메서드 내에서 수정할 수 없습니다. 링크

그런 다음 mutating 기능을 사용해야합니다.

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

1

또 다른 옵션은 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
    }
}

1

다음은 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
        }
    }
}

1

나는 이것을 생각 해냈다

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

0

여기 내 코드

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

0

여기에 나의 첫 번째 기여 :

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

다른 사람에게 감사드립니다!


1
또한 설명을 추가 할 수 있습니까?
로버트

@Robert는 다른 사람들처럼 자기 설명해야하지만 다른 점은 enum에서 init 메서드를 사용하고 있으며 기본 기본 enum이 있다는 것입니다. 따라서 Swift 플레이 그라운드의 구조 및 클래스 예제에서와 같이 enum 객체를 생성 할 때이를 알 수 있습니다.
Indra Rusmita 2015 년

0

이 실험은 역시 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에 대해 제공 한 예제에서 간단한 설명은 내부적으로 손실됩니다. 원래 값을 되돌릴 수 없습니다 (물론 클래스 / 구조 외부에 저장하지 않는 한). 이것이 SimpleEnum 예제에 대한 restore () 메서드를 생성하도록 유도 한 것입니다.이를 통해 값 사이를 앞뒤로 전환 할 수 있습니다. 이것이 누군가에게 유용하기를 바랍니다!


0

목표는 단순히 상태를 유지하고 설명을 사용하여 현재 상태를 더 쉽게 읽을 수 있도록하는 것이라고 생각했습니다.

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

0

또 다른 변형 : 관련 값을 사용하여 이전 옵션을 유지하고 표시합니다 ( "선택 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"

-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"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.