swift – 向扩展中的通用参数添加约束

前端之家收集整理的这篇文章主要介绍了swift – 向扩展中的通用参数添加约束前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有这个功能
  1. func flatten<Key: Hashable,Value>(dict: Dictionary<Key,Optional<Value>>) -> Dictionary<Key,Value> {
  2. var result = [Key: Value]()
  3. for (key,value) in dict {
  4. guard let value = value else { continue }
  5. result[key] = value
  6. }
  7. return result
  8. }

你可以看到,它将[Key:Value?]字典转换为[Key:Value]一个(没有可选).

我想用一个新的方法来扩展Dictionary类,只有这个类的值是任何类型的可选项,但是我无法为字典的通用参数添加约束.

这是我试过的:

  1. extension Dictionary where Value: Optional<Any> {
  2. func flatten() -> [Key: Any] {
  3. var result = [Key: Any]()
  4. for (key,value) in self {
  5. guard let value = value else { continue }
  6. result[key] = value
  7. }
  8. return result
  9. }
  10. }

但失败与错误

  1. Type 'Value' constrained to non-protocol type 'Optional<Any>'
在游乐场尝试此代码
  1. // make sure only `Optional` conforms to this protocol
  2. protocol OptionalEquivalent {
  3. typealias WrappedValueType
  4. func toOptional() -> WrappedValueType?
  5. }
  6.  
  7. extension Optional: OptionalEquivalent {
  8. typealias WrappedValueType = Wrapped
  9.  
  10. // just to cast `Optional<Wrapped>` to `Wrapped?`
  11. func toOptional() -> WrappedValueType? {
  12. return self
  13. }
  14. }
  15.  
  16. extension Dictionary where Value: OptionalEquivalent {
  17. func flatten() -> Dictionary<Key,Value.WrappedValueType> {
  18. var result = Dictionary<Key,Value.WrappedValueType>()
  19. for (key,value) in self {
  20. guard let value = value.toOptional() else { continue }
  21. result[key] = value
  22. }
  23. return result
  24. }
  25. }
  26.  
  27. let a: [String: String?] = ["a": "a","b": nil,"c": "c","d": nil]
  28. a.flatten() //["a": "a","c": "c"]

因为您不能在协议扩展的where子句中指定确切类型,所以您可以精确检测可选类型的一种方法是使可选UNIQUELY符合协议(例如OptionalEquivalent).

为了获取可选的包装值类型,我在自定义协议OptionalEquivalent中定义了一个typealias WrappedValueType,然后将可扩展的可扩展名,将“Wrapped”绑定到WrappedValueType,然后可以在flatten方法获取类型.

请注意,sugarCast方法只是将可选的< Wrapped>要包装?(这是完全一样的),以启用使用保护语句.

UPDATE

感谢Rob Napier的评论,我简化了&更名为sugarCast()方法,并重命名协议,使其更易于理解.

猜你在找的Swift相关文章