2017-09-04 86 views
2

我有一個功能,需要一個String標籤的說法:是否有一個雨燕的基於字符串的枚舉?

func findFooByTag(_ tag: String) -> Foo 

現在我想使代碼通過引入一個枚舉的有效標記值更短,更安全:

enum Tags: String { 
    case one 
    case two 
    case three 
} 

但我仍需要調用一個String功能:

let foo = findFooByTag(Tags.one.rawValue) 

有沒有辦法說「findFooByTag採取任何字符串-b一個枚舉「?我發現了這個:

func findFooByTag<T>(_ tag: T) -> Foo where T: RawRepresentable, T.RawValue == String 

但是,這是相當的一口。至少有可能以某種方式在類型別名下的地毯上進行掃描?

回答

1

你發現什麼看起來真棒,但我仍然會建議像下面這樣:

protocol Taggable { 
    var raw: String { get } 
} 

extension String: Taggable { 
    var raw: String { return self } 
} 

enum Tag: String, Taggable { 
    var raw: String { 
     return self.rawValue 
    } 

    case one = "aa" 
    case two = "bb" 
    case three = "cc" 
} 

func findByTag(_ tag: Taggable) { 
    if tag.raw == "aa" { ... } 
    // do something... 
} 

findByTag(Tag.one) // works 
findByTag("abc") // also works 
+0

你會如何使用''findByTag'內tag'工作?你所知道的是它是一個空的協議。 – zoul

+0

@zoul我充滿更多的內容。 – sCha

0

爲了這個目的,你可以使用任何類型的包裝對象。例如:

enum TypeNotSpecifiedTag { 
    case one 
} 

enum StringTag: String { 
    case one 
} 

enum IntTag: Int { 
    case one = 1 
} 

enum Wrapper<T>: RawRepresentable { 
    typealias RawValue = T 

    case value(T) 

    init?(rawValue: RawValue) { 
     self = .value(rawValue) 
    } 

    var rawValue: RawValue { 
     switch self { 
     case let .value(item): 
      return item 
     } 
    } 
} 

print(Wrapper.value(TypeNotSpecifiedTag.one).rawValue) // "one" 
print(Wrapper.value(StringTag.one.rawValue).rawValue) // "one" 
print(Wrapper.value(IntTag.one.rawValue).rawValue) // 1 

注意的是,根據documentation about RawValue,你並不總是需要指定RawValue,這就是爲什麼第一個例子也編譯。

0

也許你可以嘗試做到這一點與CustomStringConvertible?

enum Tags: String, CustomStringConvertible { 
    case one 
    case two 
    case three 

    var description: String { 
    return self.rawValue 
    } 
} 

func findFooByTag<T>(_ tag: T) -> Foo where T: CustomStringConvertible 

看起來更更好

或只是

func findFooByTag<T>(_ tag: CustomStringConvertible) -> Foo 
+0

'CustomStringConvertible'無關什麼OP正在努力實現。任何類都可以符合'CustomStringCollectible',唯一符合要求就是擁有一個名爲'description'的屬性'String'類型...您的函數可以用類類型調用,也可以用具有'Int'的枚舉類型調用。 'rawValue'或沒有'rawValue'可言,只要它們符合'CustomStringConvertible'。 –

0

由於沒有什麼具有共同enum「s之間的StringRawValue,對於這些沒有共同的類型或沒有協議,其一切都會符合。

然而,夫特4引入鍵入使用where子句如SE-0142描述於相關聯的類型的約束。使用這個新功能,您可以定義一個協議與相關的類型描述的enumStringrawValue,那麼你只需要做出的類型約束你Tags enum符合本協議,你將不需要類型約束在函數定義了。

class Foo {} 

protocol StringEnum { 
    associatedtype EnumType: RawRepresentable = Self where EnumType.RawValue == String 
    static func findFooByTag<EnumType>(_ tag: EnumType) -> Foo 
} 

extension StringEnum where EnumType == Self { 
    static func findFooByTag<EnumType>(_ tag: EnumType) -> Foo { 
     return Foo() 
    } 
} 

enum Tags: String, StringEnum { 
    case one 
    case two 
    case three 
} 

let foo = Tags.findFooByTag(Tags.one) 

這是實施過程中可以改進,但是這僅僅是展示如何使用where條款來實現使用及其associatedType類型約束的例子。

由於默認實現FO的協議擴展的findFooByTag FUNC,你並不需要實現功能適用於所有具有StringrawValue您的自定義枚舉類型的,你只需要他們宣告爲符合StringEnum協議。

如果您尚未安裝Xcode9,你可以玩弄使用this鏈接此代碼在IBM斯威夫特沙箱。

相關問題