协议实例的集合

时间:2015-02-13 18:33:20

标签: swift generics collections

尝试solve a problem目前无关紧要,我尝试在Swift中做一些在C#代码中非常正常的事情:定义一些协议来描述生产者 - 消费者关系,然后提供一个具体的实现制片人:

protocol Consumer
{
  func someInterestingThing( producer: Producer )

  func anotherInterestingThing( producer: Producer, happenedBefore: Bool )
}

protocol Producer
{
  func addConsumer( consumer: Consumer )

  func removeConsumer( consumer: Consumer )
}


class ConcreteProducer : Producer
{
  private var _consumers = Set<Consumer>()

  func addConsumer( consumer: Consumer ) {
    _consumers.insert(consumer);
  }

  func removeConsumer( consumer: Consumer ) {
    _consumers.remove(consumer);
  }
}

这不起作用,因为我的Consumer协议不是Hashable,它必须是进入Swift Set。 (在C#中,这没有出现,因为所有对象都继承了hashable-nature。)

好的,所以我将我的协议定义为继承自Hashable;不完全优雅,但应该工作。不!现在我使用它的所有地方,我得到:

error: protocol 'Consumer' can only be used as a generic constraint
because it has Self or associated type requirements

显然,这是因为Hashable继承了Equatable,它自己定义了==。字面意思是Self,其中{{}}}可以使用类型extra restrictions

也许还有一些我不能理解的泛型魔法,这样我就可以使用编译器满意的类型来声明集合和方法?

我可能会尝试做一些有趣的事情,比如用更抽象的术语定义存储,并在添加和删除方法上强制执行协议一致性。但AnyObject未实现Hashable。 (有更好的选择吗?)

我可以尝试将消费者打包在一个实现Hashable的私有包装器中,但是我需要能够比较这些包装器,这取决于消费者的身份,然后看起来像我回到了同一条船上。

我想要的只是将一堆这些东西放在一个集合中,而不再了解它们而不是绝对必要。我该怎么做?

1 个答案:

答案 0 :(得分:1)

这个怎么样?

protocol Consumer: class {
    func someInterestingThing( producer: Producer )
    func anotherInterestingThing( producer: Producer, happenedBefore: Bool )
}

protocol Producer {
    func addConsumer( consumer: Consumer )
    func removeConsumer( consumer: Consumer )
}

class ConcreteProducer : Producer {
    private var _consumers = [ObjectIdentifier:Consumer]()

    func addConsumer( consumer: Consumer ) {
        _consumers[ObjectIdentifier(consumer)] = consumer
    }

    func removeConsumer( consumer: Consumer ) {
        _consumers[ObjectIdentifier(consumer)] = nil
    }
}
  • Consumer声明为class仅协议
  • 使用Dictionary<ObjectIdentifier, Consumer>代替Set<Consumer>