代码之家  ›  专栏  ›  技术社区  ›  Michael SarpErdag

将泛型结构与协议一起使用

  •  3
  • Michael SarpErdag  · 技术社区  · 8 年前

    似乎swift泛型可以很好地工作,只要我不尝试以任何实际的方式组合它们。我使用的是swift 4.1,我想创建一个只包含弱引用的泛型数组。我可以定义为 WeakList<T> . 到目前为止还不错。但是:我想用一个协议 T . 斯威夫特说不行。

    import Foundation
    
    protocol Observer: class {
        func stateChanged(sender: SomeClass, newState: Int)
    }
    
    struct WeakList<T> where T: AnyObject {
        struct Ptr {
            weak var p: T?
        }
        private var storage: [Ptr] = []
        var aliveObjects: [T] {
            var result: [T] = []
            for ptr in storage {
                if let p = ptr.p {
                    result.append(p)
                }
            }
            return result
        }
        mutating func add(_ obj: T) {
            storage.append(Ptr(p: obj))
        }
        // Let's ignore for a moment that this implementation leaks memory badly.
    }
    
    class SomeClass {
        var someVar: WeakList<Observer> = WeakList<Observer>()
        // Error: WeakList requires that 'Observer' be a class type
    
        var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
    }
    

    (这不是我的原始代码,而是一个最小的可验证示例,其中包含了足够的细节,因此没有人可以说“只是从结构中删除anyobject约束”)。

    我想我要做的是不可能的。或者是?当我尝试使用swift泛型时,5次中有4次是令人沮丧的,但后来我发现我试图做的是不可能的。(顺便说一下,我可以很容易地在objective-c中实现相同的东西。)

    • 我试着改变 class 约束到 AnyObject constraint=>也不起作用。
    • 我试着改变 任何对象 约束到 constraint=>甚至不编译。
    • 把它改成 protocol Observer where Self: NSObject 什么都没变。 NSObject 是类类型, Observer 是一个 NSO对象 . 应该是这样的 观察者 是类类型。“是一种”的关系在这里似乎不具有传递性。
    1 回复  |  直到 8 年前
        1
  •  1
  •   Michael SarpErdag    8 年前

    对于当前实现,您不能从 AnyObject . 你所能做的就是为你的协议创建一个类型擦除器并使用它。现在你的类型擦除器可以从 任何对象 .

    像这样的:

    protocol Observer {
        func stateChanged(sender: SomeClass, newState: Int)
    }
    
    class AnyObserver: NSObject, Observer {
        private let observer: Observer
    
        init(observer: Observer) {
            self.observer = observer
        }
    
        func stateChanged(sender: SomeClass, newState: Int) {
            observer.stateChanged(sender: sender, newState: newState)
        }
    }
    
    struct WeakList<T> where T: AnyObject {
        struct Ptr {
            weak var p: T?
        }
        private var storage: [Ptr] = []
        var aliveObjects: [T] {
            var result: [T] = []
            for ptr in storage {
                if let p = ptr.p {
                    result.append(p)
                }
            }
            return result
        }
        mutating func add(_ obj: T) {
            storage.append(Ptr(p: obj))
        }
        // Let's ignore for a moment that this implementation leaks memory badly.
    }
    
    class SomeClass {
        var someVar: WeakList<AnyObserver> = WeakList<AnyObserver>()
    
        var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
    }