如何在Swift协议中要求定义枚举

37

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

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

你的使用场景是什么? - JAL
你为什么想要这个?你想达到什么目的? - Alexander
2个回答

45
协议可以有“关联类型”,这些类型只需要在任何子类中遵循即可。
enum MyEnum: String {
    case foo
    case bar
}

protocol RequiresEnum {
    associatedtype SomeEnumType: RawRepresentable where SomeEnumType.RawValue: StringProtocol

    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(someEnumType: .bar)

编辑:必须遵守associatedtype


3
不错,虽然没有强制要求SomeEnumType必须是枚举类型。但它能正常工作。 - MH175
1
我自己解决这个问题的方法与此类似,但这种方法会将枚举的可访问性暴露给那些甚至没有采用该协议的控制器。我想知道如何将枚举范围限定在采用协议的范围内。但由于枚举不允许在协议内部使用,是否有其他表示情况的方式而不使用枚举? - yohannes

21

我认为你可以使用符合 RawRepresentable 协议的 associatedtype 来实现。

以下是一个示例:

protocol SomeProtocol {
    associatedtype SomeType: RawRepresentable
}

如果需要指定RawRepresentable的类型,比如String,你可以这样做:

如果需要指定RawRepresentable的类型,比如String,你可以这样做:

protocol SomeProtocol {
    associatedtype SomeType: RawRepresentable where SomeType.RawValue: StringProtocol
}

现在,如果您尝试使用除了将String作为RawRepresentableenum以外的任何其他方法来实现协议,则会出现编译器错误。

希望这可以帮助您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接