【问题标题】:Set and protocols in SwiftSwift 中的集合和协议
【发布时间】:2015-10-17 17:14:26
【问题描述】:

我想用对应于 Hashable 协议和自定义协议的值初始化一个 Set。

我试过了:

protocol CustomProtocol: Hashable {}

let set = Set<CustomProtocol>()

但是 Xcode 抱怨:

使用“CustomProtocol”作为符合协议的具体类型 不支持“可哈希”

我怎样才能做到这一点?

提前致谢。

【问题讨论】:

  • 中的对象已经被要求符合Hashable。
  • 如果 CustomProtocol 不符合 Hashable,Xcode 会抱怨 CustomProtocol 不符合它。看来我错过了什么。

标签: ios swift


【解决方案1】:

你不能做你想做的事情的直接原因是 Hashable 是一个通用协议。因此它——或从它派生的协议——不能用作 Set 的元素类型。泛型类型只能用作另一个泛型中的约束。您会注意到您也不能声明 Set&lt;Hashable&gt;,即使集合的元素类型必须符合到 Hashable。

最简单的方法是制作,不是一组协议,而是一组某种对象类型。例如,如果 S 是一个符合 CustomProtocol 的结构(因为它符合 Hashable 以及 CustomProtocol 需要的任何其他内容),则可以声明一组 S。

例子:

protocol CustomProtocol: Hashable {

}

func ==(lhs:S,rhs:S) -> Bool {
    return lhs.name == rhs.name
}

struct S : CustomProtocol {
    var name : String
    var hashValue : Int { return name.hashValue }
}

let set = Set<S>()

如果您要解决的问题是您想要一个混合类型的集合,但这些类型在某种程度上彼此相等,那么这与协议扩展解决的问题完全相同,正如在讨论中所解释的那样面向协议的 WWDC 2015 视频。

但是让你的所有类型类都派生自 NSObject 会更简单。当然,您仍然可以让它们采用某种辅助协议,但该集合不会被定义为该协议的集合,而是 NSObject 的集合。

【讨论】:

  • 谢谢。但是我想从不同的类中插入我的集合对象,而不是一个。这就是我不想创建“一组协议”的原因。
  • 查看我修改后的答案。
  • 最简单的方法当然是让你的所有类都派生自 NSObject,正如你已经被告知的那样。
  • 我正在寻找一个听起来像协议扩展的答案。我在视频发布时观看了视频,但我不知道在这种情况下如何使用这种方法。现在,一个数组就可以完成这项工作。我稍后会再看一遍。 (顺便说一句,我喜欢你的书,很高兴你回答了我的一个问题)
  • 在视频中,问题是为协议定义 equatable,这就是您在使用 CustomProtocol 时所面临的问题 - 我们如何知道两个 CustomProtocol 采用者何时彼此是 ==?如果没有 == 的定义来回答这个问题,我们就无法实现 Hashable。他通过协议扩展约束where Self:Equatable 解决了这个问题,该扩展定义了一个额外的等效函数。通过这种方式,您将能够保证== 对您的任何一对 Set 成员都是有意义的。我不会重复他的代码,因为你想做的正是他所做的。
【解决方案2】:

在 Swift 3 中,一种解决方案是使用 AnyHashable structure

例如,要创建 Observers/Observable 模式,我们可以这样做:

protocol Observer {
    func observableDidSomething(_ observable: Observable)
}

class Observable {
    private var observersSet: Set<AnyHashable> = []

    private var observers: [Observer] {
        return observersSet.flatMap { $0 as? Observer }
    }

    func add<O>(_ observer: O) where O : Observer, O : Hashable {
        observersSet.insert(observer)
    }

    func remove<O>(_ observer: O) where O : Observer, O : Hashable {
        observersSet.remove(observer)
    }

    // ...

    private func doSomething() {
        // do something ...
        observers.forEach { $0.observableDidSomething(self) }
    }
} 

请注意,我将Hashable 协议与我的协议Observer 分开。

【讨论】:

  • 有人能解释一下添加和删除函数的输入语法吗?我不熟悉 和其中 O : Observer, O : Hashable 语法。
猜你喜欢
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 1970-01-01
相关资源
最近更新 更多