#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. Спасибо за ответ, ясное и простое объяснение.