何时在Swift中使用带约束的关联类型?

时间:2019-06-08 07:35:41

标签: swift protocols

    protocol Item {
      init(name: String)
    }

   //case1
    protocol SomeProtocol {
        associatedtype ItemType: Item
        var items: [ItemType] { get set }
    }

    //case2
    protocol SomeProtocol {
          var items: [Item] { get set }
    }

案例1和案例2有什么区别?据我的理解,案例1表示item是实现Item协议的任何类型的数组,而case 2则表示协议本身不能做同样的事情因此,item再次是一个实现Item协议的对象数组。

1 个答案:

答案 0 :(得分:0)

  

根据我的理解,情况1表示项目是实现项目协议的任何类型的数组,情况2表示不能启动协议本身的同一件事,因此情况下的项目又是数组实现Item协议的对象。

让我们给您的协议起更好的名字,以证明这两种情况是如何不同的。让我们将SomeProtocol重命名为ItemStorage。另外,假设有两个符合Item的类,FooItemBarItem

现在,我想创建两个实现ItemStorage的类,分别称为FooItemStorageBarItemStorage。我希望他们只能存储各自的Item类型。如果是第一种情况,我可以很容易地做到这一点:

class FooItemStorage: ItemStorage {
    typealias ItemType = FooItem
    var items: [FooItem] = []

    ...
}

class BarItemStorage: ItemStorage {
    typealias ItemType = BarItem
    var items: [BarItem] = []

    ...
}

但是,在情况2中,数组必须为[Item]类型,因此上面的代码将无法编译。我必须做这样的事情:

class FooItemStorage: ItemStorage {
    typealias ItemType = FooItem
    var items: [Item] {
        get { return myItems }
        set {
            myItems = newValue as? [FooItem] ?? myItems
        }
    }
    var myItems: [FooItem] = []
    ...
}

我必须声明一个名为myItems的额外属性,该属性具有我想要的类型[FooItem],并将items的getter和setter委托给myItems。另外,从客户端代码的角度来看,似乎FooItemStorage现在可以存储任何种类的项目。

请注意,这并不是说具有关联类型的协议总是更好。具有关联类型的协议不能用作变量的类型。因此,如果不需要FooItemStorageBarItemStorage之类的符合类需要不同类型的东西,并且希望将协议用作变量的类型,则不应使用关联的类型。 / p>