Swift中任何协议的通用约束

时间:2015-11-17 08:32:34

标签: ios swift automatic-ref-counting

是否可以将通用类型约束为接受Swift中的协议?

我已经实现了包装器以获得弱对象列表,我需要将其扩展到协议。

protocol Incrementable: class {
    func inc()
}

class Counter: Incrementable {
    var n: Int = 0

    func inc() {
        n += 1
    }
}

struct Weak<T: AnyObject> {
    weak var value : T?
    init (value: T?)
    {
        self.value = value
    }
}

var cnt: Counter? = Counter()

let counters : [Weak<Counter>] = [Weak(value: cnt), Weak(value: Counter())]

for counter in counters
{
    counter.value?.inc()
}

现在,如果我想存储任何实现Incrementable的对象,我必须使用AnyObject,这不是非常类型安全的,还包括as?强制转换

let counters : [Weak<AnyObject>] = [Weak(value: cnt), Weak(value: Counter())]

for counter in counters
{
    (counter.value as? Incrementable)?.inc()
}

我想要的代码是

let counters: [Weak<Incrementable>] = [Weak(value: cnt), Weak(value: Counter())]

for counter in counters
{
    counter.value?.inc()
}

当然,以上代码无法编译并失败:

  

使用'Incrementable'作为符合协议的具体类型   不支持'AnyObject'

是否可以编写Weak包装器,以便它可以接受并存储对协议的弱引用?

虽然我的问题的根本原因与Using as a concrete type conforming to protocol AnyObject is not supported中的问题处理哈希表相同,但我需要使用允许重复条目的列表的解决方案。

1 个答案:

答案 0 :(得分:2)

以下answer指出了正确的方向,我能够提出以下解决方案来实现允许重复和nil(便利)条目的协议引用的弱列表。

struct Weak<T>
{
    weak var value: AnyObject?
    init (value: T?)
    {
        if value != nil
        {
            guard value is AnyObject else { fatalError("Object (\(value)) should be subclass of AnyObject") }
            self.value = value as? AnyObject
        }
    }
}

class WeakList<T>: SequenceType
{
    var items : [Weak<T>] = []

    func add(item: T?)
    {
        items.append(Weak(value: item))
    }

    func generate() -> AnyGenerator<T>
    {
        var nextIndex = items.count - 1

        return anyGenerator
        {
            while nextIndex >= 0
            {
                let item = self.items[nextIndex--]
                if item.value != nil
                {
                   return item.value as? T
                }
            }
            return nil
        }
    }
}

let incrementables = WeakList<Incrementable>()

incrementables.add(Counter())
incrementables.add(cnt)
incrementables.add(nil)
incrementables.add(Counter())
incrementables.add(cnt)

for counter in incrementables
{
    counter.inc()
}
相关问题