【问题标题】:How to define a protocol with an array of a protocol with an associated type如何使用具有关联类型的协议数组定义协议
【发布时间】:2016-04-27 14:17:46
【问题描述】:

我正在尝试创建一个协议 (AppStore),它要求符合者实现符合具有关联类型的协议 (订阅者) 的项目 (订阅) 数组。

目标 你可以把 AppStore 想象成一个 NSNotificationCenter。我想添加订阅者(比如 addObserver...)。当发生某些事情时,在订阅者上调用handleNewState(如handleNotification :) 并传入一个实际上设置了一些变量的AppState 一致性。库存 AppState 没有任何可用的属性。

public protocol AppStore {
    //trying to have an array of subscriptions in the protocol
    //but a concrete Subscriber type needs to be specified, I thought a generic Subscriber would be more flexible here?
    var subscriptions:[Subscription<>]{get set}// Reference to generic type 'Subscription' requires arguments in <...>

    associatedtype AppStateType:AppState
    var appState:AppStateType { get set }
}
extension AppStore {
    //so that AppStore can implement this function
    public mutating func subscribe<T:protocol<Subscriber, AnyObject>>(aSubscriber:T){
        subscriptions.append(Subscription(sub:aSubscriber))
    }
}

public protocol Subscriber {
    associatedtype AppStateType
    func handleNewState(newState:AppStateType)
}

public struct Subscription <T:protocol<Subscriber, AnyObject>> {
    private weak var subscriber:T? = nil
    init(sub:T){
        self.subscriber = sub
    }
}
public protocol AppState { }

我应该如何定义 var subscriptions:[Subscription&lt;&gt;]? 或者我应该以不同的方式来做这件事

我会这样使用它

public struct OSXAppState:AppState {
     var someStateProp:Int = 0
}
extension NSView : Subscriber { 
    public func handleNewState(newState:OSXAppState){
         if newState == 1 { //do this }
         else { //do that }
    } 
}
public struct OSXAppStore : AppStore {
    public typealias GenericSubscriber = NSView//???: something more generic "anything that implements Subscriber"
    public var subscriptions: [Subscription<GenericSubscriber>] = []
    public var appState: AppState = OSXAppState()
}

【问题讨论】:

  • 您能更详细地描述您的目标吗?你想用这段代码解决什么问题?这可能不是实现该目标的最直接方式。

标签: swift


【解决方案1】:

我假设您遵守AnyObject 以便能够使用weak。这可以通过使协议仅类更简单地完成。我改变了协议组成

protocol&lt;Subscriber, AnyObject&gt;

protocol Subscriber: class

我也加了

associatedtype GenericSubscriber: SubscriberType

允许泛型

Subscription&lt;T: SubscriberType&gt;

在数组中使用。

public protocol Subscriber: class {
  associatedtype AppStateType:AppState
  func handleNewState(newState:AppStateType)
}

public struct Subscription<T:Subscriber> {
  private weak var subscriber:T?
  init(sub:T){
    self.subscriber = sub
  }
}

public protocol AppState { }

public protocol AppStore {
  // Allows Subscription<T:Subscriber> to be used as an array element
  associatedtype GenericSubscriber:Subscriber

  var subscriptions:[Subscription<GenericSubscriber>]{get set}
  var appState:AppState { get set }
}

extension AppStore {
  // The concrete type of GenericSubscriber is inferred from this context
  public mutating func subscribe(aSubscriber: GenericSubscriber){
    subscriptions.append(Subscription<GenericSubscriber>(sub:aSubscriber))
  }
}

public struct OSXAppState:AppState {
  var someStateProp:Int
}
extension NSView : Subscriber {
  public func handleNewState(newState:OSXAppState){
  }
}

【讨论】:

  • associatedtype AppStateType 是这里的关键部分。我想创建一个使用它自己的 AppState 类型的 AppState 构造器。 public struct OSXAppState:AppState { }。没有 AppStateType 我该怎么做extension NSView : Subscriber { public func handleNewState(newState: OSXAppState ){ } } (newState: OSXAppState )
  • 我更新了答案以反映您如何使用代码。
  • 谢谢!那么,我将如何实现一个符合 AppStore 的结构呢?我的使用只允许 NSView 但我会允许任何符合订阅者的东西。我更新了我的用例代码以包含 OSXAppStore。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 2022-11-27
相关资源
最近更新 更多