Est-il possible qu'un protocole nécessite la définition d'une énumération?
//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
}
}
Ce n'est pas possible dans Swift. Si c'était possible, il est difficile de savoir comment vous l'utiliseriez directement, car vous ne pourriez vous référer à aucun des cas (car vous ne savez pas ce qu'ils sont). Vous devrez éventuellement as
transtyper, ce qui brise tout le point du protocole. (On pourrait imaginer des utilisations si enum
était un type de collection, mais ce n'est pas le cas, et si c'était le cas, vous pourriez simplement exiger "un type de collection.")
Les protocoles peuvent avoir associatedtypes
qui aurait juste besoin d'être respecté dans n'importe quelle sous-classe:
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)
Modifier: Le associatedtype
doit être respecté
Je pense que vous pouvez le faire avec un associatedtype
qui adhère à RawRepresentable
Voici un exemple:
protocol SomeProtocol {
associatedtype SomeType: RawRepresentable
}
Si vous devez spécifier le type de RawRepresentable
comme String
par exemple, vous pouvez le faire:
protocol SomeProtocol {
associatedtype SomeType: RawRepresentable where SomeType.RawValue: StringProtocol
}
Vous aurez maintenant une erreur de compilation si vous essayez d'implémenter le protocole avec autre chose qu'un enum
qui a String
comme RawRepresentable
. J'espère que ça aide.