代码之家  ›  专栏  ›  技术社区  ›  Bartłomiej Semańczyk

如何定义特定类型字典的扩展?

  •  2
  • Bartłomiej Semańczyk  · 技术社区  · 7 年前

    我创造了 typealias :

    typealias Multilang = [String: Any]
    

    现在我想用属性扩展那本字典 localized . 有可能吗?

    我需要怎么使用它?

    let dictionary: Multilang = ["en": "b", "pl": "d"]()
    let value = dictionary.localized
    

    我试着这样做:

    extension Dictionary where Dictionary: Multilang {
        var localized: String {
            print("self: \(self)")
            return "hello"
       }
    }
    

    但没用。为什么?

    Type 'Dictionary(Key, Value)' constrained to non-protocol, non-class type 'Multilang' (aka 'Dictionary(String, Any)')
    
    3 回复  |  直到 7 年前
        1
  •  2
  •   Ilya Kharabet    7 年前

    您可以编写这样的扩展:

    extension Dictionary where Key == String, Value == Any {
        var localized: String {
            print("self: \(self)")
            return "hello"
        }
    }
    

    或:

    extension Dictionary where Dictionary == Multilang
    
        2
  •  2
  •   Arkku    7 年前

    (不幸的是)不能使用 typealias 这样,因为它不会创建新类型。例如,您可以 typealias Foo = [String: Any] typealias Bar = [String: Any] ,但是 Foo Bar 仍然是同一类型。

    所以要么你就把所有的 [String: Any] 字典,或者需要创建包装类型(也不能为 Dictionary 因为它是 struct ). 例如:

    struct Multilang<Element> {
        var dictionary: [String: Element]
        var localized: Element? {
            return dictionary[currentLanguage]
        }
    }
    

    缺点是需要定义所有要使用的包装器方法和属性 multilang.foo 语法,但是如果有足够的 multilang.localized ,你可以把剩下的都做完 multilang.dictionary.foo .

    你也可以实现 ExpressibleByDictionaryLiteral 要轻松创建这些对象,请执行以下操作:

    extension Multilang: ExpressibleByDictionaryLiteral {
        init(dictionaryLiteral elements: (String, Element)...) {
            dictionary = .init(elements) { $1 }
        }
    }
    
    let multilang: Multilang = [ "en": "English", "pl": "Polish" ]
    
        3
  •  1
  •   Chris    7 年前

    对于Swift 3及更高版本,您可以尝试此方法来扩展类型为 [String: Any] .

    extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
        // Your extension code
        var localized: String {
        print("self: \(self)")
        return "hello"
    }
    

    ExpressibleByStringLiteral 是一个协议 String StaticString 类型符合。

    不能仅将其应用于类型别名,因为 Multilang 只是一个标签 [String:Any] ,所以即使您可以扩展它,它也会扩展此类型的所有词典。