Когда использовать связанный тип с ограничением в Swift? - PullRequest
0 голосов
/ 08 июня 2019
    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, а случай 2 - это то же самое, что и сами протоколы.не может быть инициировано. Таким образом, элементы в случае, если это снова массив объектов, реализующий протокол Item.

1 Ответ

0 голосов
/ 08 июня 2019

Насколько я понимаю, случай 1 говорит, что элементы - это массив любого типа, который реализует протокол Item, а случай 2 - это то же самое, что и сами протоколы не могут быть инициированы. Таким образом, элементы в случае, если снова массив объектов, реализующих протокол Item.

Давайте назовем ваши протоколы более точными названиями, чтобы продемонстрировать, как эти два случая различны. Давайте переименуем SomeProtocol в ItemStorage. Также, скажем, есть два класса, которые соответствуют Item, FooItem и BarItem.

Теперь я хочу создать два класса, которые реализуют ItemStorage с именами FooItemStorage и BarItemStorage. Я хочу, чтобы они могли хранить только свой соответствующий тип Item. Если бы это был случай 1, я мог бы сделать это очень легко:

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 myItems. Кроме того, с точки зрения клиентского кода это выглядит так, как будто FooItemStorage теперь может хранить любые элементы.

Обратите внимание, это не означает, что протоколы со связанными типами всегда лучше. Протоколы со связанными типами не могут использоваться в качестве типа переменной. Так что если вам не нужно что-то вроде FooItemStorage и BarItemStorage, где соответствующие классы нуждаются в разных типах, и вы хотите использовать протокол в качестве типа переменной, вам не следует использовать связанные типы.

...