【问题标题】:Add object to an array that confirm to the protocol that has associated type in it将对象添加到数组中,以确认其中具有关联类型的协议
【发布时间】:2023-01-31 16:51:47
【问题描述】:

我在编写将对象放入observers 数组的代码时遇到问题。有问题的对象实现了Observer 协议。 这是显示我想做什么的代码:

protocol Observer {
    associatedtype ValueType
    func update(value: ValueType)
}

struct Subject<T> {
    private var observers = Array<Observer>()

    mutating func attach(observer: Observer) {
        observers.append(observer)
    }

    func notyfi(value: T) {
        for observer in observers {
            observer.update(value: value)
        }
    }
}

【问题讨论】:

    标签: swift generics swift-protocols generic-associated-types


    【解决方案1】:

    如果您的部署目标至少是 2022 年末的版本(iOS 16、macOS 13 等),您可以使用 constrained existential

    protocol Observer<ValueType> {
        associatedtype ValueType
        func update(value: ValueType)
    }
    
    struct Subject<T> {
        private var observers = Array<any Observer<T>>()
    
        mutating func attach(observer: any Observer<T>) {
            observers.append(observer)
        }
    
        func notify(value: T) {
            for observer in observers {
                observer.update(value: value)
            }
        }
    }
    

    如果您的部署目标较早,则 Swift 运行时不支持受限存在。 (来自 SE-0353:“值得注意的是,此功能需要对 Swift 运行时和 ABI 进行修订,它们既不向后兼容也不向后部署到现有操作系统版本。”)但是您可以改用闭包:

    protocol Observer<ValueType> {
        associatedtype ValueType
        func update(value: ValueType)
    }
    
    struct Subject<T> {
        private var observers: [(T) -> Void] = []
        
        mutating func attach<O: Observer>(observer: O)
        where O.ValueType == T
        {
            observers.append { observer.update(value: $0) }
        }
    
        func notify(value: T) {
            for observer in observers {
                observer(value)
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      为什么不使用 Observer 作为通用参数?

      struct Subject<O: Observer> {
      
          typealias T = O.ValueType
      
          private var observers = Array<O>()
      
          mutating func attach(observer: O) {
              observers.append(observer)
          }
      
          func notyfi(value: T) {
              for observer in observers {
                  observer.update(value: value)
              }
          }
      }
      

      【讨论】:

      • 此解决方案具有以下限制:存储在主题中的所有观察者必须具有相同的类型。根据我使用观察者模式的经验,这通常是不可接受的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      相关资源
      最近更新 更多