2016-10-17 4 views
1

Je ne trouve pas la syntaxe, mais je veux faire quelque chose comme ceci:Les enum Swift peuvent-elles être déduites et restreintes génériquement?

class MyClass { 
    let stringValue: String // filled in later 
    let integerValue: Int // filled in later 

    init(stringValue: String) { 
     self.stringValue = stringValue 
     self.integerValue = stringValue.hashValue 
    } 

    init(integerValue: Int) { 
     self.integerValue = integerValue 
     self.stringValue = String(integerValue) 
    } 
} 

extension MyClass { 
    //      This is invalid syntax, but I think you can understand 
    //   vvvvvvvvv I'm trying to give back an enum whose type is inferred 
    var enumValue<T: enum>: T? { 
     get { 
      // This is also invalid; I want to check the type of the enum's raw value 
      if T is String { 
       return T(rawValue: self.stringValue) 
      } else if T is Int { 
       return T(rawValue: self.integerValue) 
      } else { 
       return nil 
      } 
     } 
    } 
} 

L'usage serait comme:

enum MyEnum: String { 
    case foo 
    case bar 
} 

func baz(_ some: MyClass) { 
    if let myEnum: MyEnum = some.enumValue { 
     print(myEnum) 
    } 
} 

let some = MyClass(stringValue: "foo") 
baz(some) // prints "foo" 

Est-ce possible à Swift? Autrement dit, pour avoir un champ ou une fonction de type générique dont le type est restreint à enums et déduit en fonction de l'utilisation, utilisez-le pour instancier une valeur enum?

Répondre

1

Une solution possible serait une fonction surchargée générique:

extension MyClass { 
    func enumValue<T: RawRepresentable>() -> T? where T.RawValue == String { 
      return T(rawValue: stringValue) 
    } 
    func enumValue<T: RawRepresentable>() -> T? where T.RawValue == Int { 
      return T(rawValue: integerValue) 
    } 
} 

qui est alors appelé comme

func baz(_ some: MyClass) { 
    if let myEnum: MyEnum = some.enumValue() { 
     print(myEnum) 
    } 
} 

Sinon, passer le type ENUM comme argument:

extension MyClass { 
    func enumValue<T: RawRepresentable>(_ type: T.Type) -> T? where T.RawValue == String { 
      return T(rawValue: stringValue) 
    } 
    func enumValue<T: RawRepresentable>(_ type: T.Type) -> T? where T.RawValue == Int { 
      return T(rawValue: integerValue) 
    } 
} 

et appelez-le comme

func baz(_ some: MyClass) { 
    if let myEnum = some.enumValue(MyEnum.self) { 
     print(myEnum) 
    } 
} 
+0

Magnifique! Presque exactement ce que je cherchais: D –