Почему я не могу получить доступ к члену generic в swift

#swift #generics #swift-protocols

Вопрос:

Я не могу свыкнуться с этим. У меня есть код ниже. Мой вопрос в том. Почему я не могу получить доступ к идентификатору в функции compareId (ошибка, которую я получаю, — это «Значение типа ‘T.ItemType» не имеет идентификатора члена»»), но в функции compareIdW я могу получить доступ к идентификатору? Кто-нибудь может мне это объяснить? Я буду признателен за любую помощь. Спасибо

 import Foundation  protocol ProtoA: Identifiable{  var id: UUID { get } }  protocol ProtoB: Identifiable{  associatedtype ItemType = ProtoA  var id: UUID { get }  var arrayOfItems: [ItemType] { get } }  class Mlt;T:ProtoBgt;{  var itemA: T.ItemType?  init(itemA: T.ItemType?) {  self.itemA = itemA  }   // This does not work  func compareId(of item: T.ItemType) -gt; Bool {  return item.id == self.itemA?.id // when  }   // But this does   func compareIdWlt;U: ProtoAgt;(of item: U) -gt; Bool where U == T.ItemType {  return item.id == self.itemA?.id  }  }  

Ответ №1:

Это потому T.ItemType , что неоднозначно.

В тот момент, когда компилятор смотрит на ваше выражение, все, что он действительно знает, это то, что T.ItemType это an associatedType . На самом деле он не знает, какими свойствами ItemType может обладать конкретный экземпляр, которому присвоен.

Рассмотрим этот код:

 struct Marshmallow { }  struct SmoresStruct : ProtoB {  typealias ItemType = Marshmallow   var id: UUID = UUID()  var arrayOfItems: [Self.ItemType] = Arraylt;Marshmallowgt;() }  class SmoresClass : Mlt;SmoresStructgt; { }   

SmoresStruct является a struct , удовлетворяющим ограничению, которое он реализует ProtoB , и его можно использовать для создания SmoresClass (подкласса class M ), поскольку он удовлетворяет всем ограничениям, которые вы наложили на общий параметр class M . Но ItemType , Marshmallow , это не Identifiable так на том этапе реализации class M , когда вы пытаетесь подразумевать, что T.ItemType должно иметь id свойство, это один из случаев, когда этого не происходит.

Вам нужно дополнительное ограничение на объявление M класса:

 class Mlt;T : ProtoBgt; where T.ItemType : Identifiable {  ... }  

Теперь, если вы попытаетесь использовать Marshmallow в качестве ItemType , вы получите:

Введите «SmoresStruct».Тип элемента «(он же «Зефир») не соответствует протоколу «Идентифицируемый»

Комментарии:

1. Спасибо за ответ, ясное и простое объяснение.