Home > OS >  Why I can not access member of generic in swift
Why I can not access member of generic in swift

Time:10-21

I can't wrap my head around this. I have the code below. My question is. Why I can not access id in the function compareId (the error, that I am getting is "Value of type 'T.ItemType' has no member 'id'"), but in the function compareIdW I can access the id? Can anyone explain this to me? I will appreciate every help. Thanks

import Foundation

protocol ProtoA: Identifiable{
    var id: UUID { get }
}

protocol ProtoB: Identifiable{
    associatedtype ItemType = ProtoA
    var id: UUID { get }
    var arrayOfItems: [ItemType] { get }
}

class M<T:ProtoB>{
    var itemA: T.ItemType?
    init(itemA: T.ItemType?) {
        self.itemA = itemA
    }

    // This does not work
    func compareId(of item: T.ItemType) -> Bool {
        return item.id == self.itemA?.id // when
    }

    // But this does

    func compareIdW<U: ProtoA>(of item: U) -> Bool where U == T.ItemType {
        return item.id == self.itemA?.id
    }

}

CodePudding user response:

It's because T.ItemType is ambiguous.

At the point that the compiler is looking at your expression all it really knows is that T.ItemType is an associatedType. It doesn't really know what properties a particular instance assigned to ItemType might have.

Consider this code:

struct Marshmallow {
}

struct SmoresStruct : ProtoB {
    typealias ItemType = Marshmallow

    var id: UUID = UUID()
    var arrayOfItems: [Self.ItemType] = Array<Marshmallow>()
}

class SmoresClass : M<SmoresStruct> {
} 

SmoresStruct is a struct that satisfies the constraint that it implements ProtoB, and it can be used to create SmoresClass (a subclass of class M) because it satisfies all the constraints you've placed on the generic parameter of class M. But the ItemType, Marshmallow, is not Identifiable so at the point in the implementation of class M where you try to imply that T.ItemType should have an id property, this is one instance where it does not.

You need an additional constraint on your declaration of the M Class:

class M<T : ProtoB> where T.ItemType : Identifiable {
   ...
}

Now if you try to use Marshmallow as an ItemType you will get:

Type 'SmoresStruct.ItemType' (aka 'Marshmallow') does not conform to protocol 'Identifiable'

  • Related