如何在Swift协议中定义枚举

时间:2016-05-20 18:26:46

标签: swift protocols

是否可以让协议要求定义枚举?

//trying to do this
protocol JSONEncodable {
    enum PropertyName // Type not allowed here
    func valueForProperty(propertyName:PropertyName) -> Any
}

//which would be implemented like this
struct Person : JSONEncodable {
    var firstName : String
    var lastName : String

    enum PropertyName {
        case FirstName
        case LastName
        func allValues() {
            return [Person.PropertyName.FirstName, Person.PropertyName.LastName]
        }
        func stringValue() {
            return "\(self)"
        }
    }
    func valueForProperty(propertyName:PropertyName) -> Any {
        switch propertyName {

        case .FirstName:
            return firstName

        case .LastName:
            return lastName
        }
    }
}

//so that I could do something like this
extension JSONEncodable {

    func JSONObject() -> [String:AnyObject] {
        var dictionary = [String:AnyObject]()
        for propertyName in PropertyName.allValues {
            let value = valueForProperty(propertyName)

            if let valueObject = value as? AnyObject {
                dictionary[propertyName.stringValue()] = valueObject

            }else if let valueObject = value as? JSONEncodable {
                dictionary[propertyName.stringValue()] = valueObject.JSONObject()
            }

        }
        return dictionary
    }
}

3 个答案:

答案 0 :(得分:16)

协议可以有associatedtypes,只需要在任何子类中遵守:

enum MyEnum {
    case foo
    case bar
}

protocol RequiresEnum {
    associatedtype SomeEnumType

    func doSomethingWithEnum(someEnumType: SomeEnumType)
}

class MyRequiresEnum: RequiresEnum {
    typealias SomeEnumType = MyEnum

    func doSomethingWithEnum(someEnumType: SomeEnumType) {
        switch someEnumType {
        case .foo:
            print("foo")
        case .bar:
            print("bar")
        }
    }
}

let mre = MyRequiresEnum()
mre.doSomethingWithEnum(.bar)

修改associatedtype 必须才能加入

答案 1 :(得分:5)

这在Swift中是不可能的。如果有可能,则不清楚如何直接使用它,因为您无法参考任何案例(因为您不知道它们是什么)。你最终必须as施放,这打破了协议的全部要点。 (如果enum是集合类型,可以想象使用它,但它不是,如果它是你可能只需要#34;集合类型。")

答案 2 :(得分:0)

我认为您可以使用符合associatedtype的{​​{1}}来做到这一点

这是一个例子:

RawRepresentable

如果您需要指定protocol SomeProtocol { associatedtype SomeType: RawRepresentable } 的类型,例如RawRepresentable,则可以执行以下操作:

String

现在,如果您尝试使用除protocol SomeProtocol { associatedtype SomeType: RawRepresentable where SomeType.RawValue: StringProtocol } enum的{​​{1}}以外的其他任何东西来实现该协议,则会遇到编译器错误。 希望对您有所帮助。