Hello I want to build something like below:
protocol BaseEntity: Identifiable {
var id: UUID { get set }
}
protocol DataStore {
associatedtype T: BaseEntity
typealias CompleteHandler<T> = ((Result<T, Error>) -> Void)
func read(with id: T.ID, completion: CompleteHandler<T>)
}
but in concrete implementation I want to make use of the UUID that was defined in the BaseEntity protocol:
class Storage<Entity: BaseEntity>: DataStore {
func read(with id: Entity.ID, completion: CompleteHandler<Entity>) {
// here, how to use that id as a UUID?
}
}
I don't know how to do it really, to define that there must be an object conforming to BaseEntity and would like to use that UUID id property in the concrete implementation.
I don't want to do it like:
func read(with id: Entity.ID, completion: CompleteHandler<Entity>) {
guard let uuid = id as? UUID else {
return
}
// more code goes here...
}
How I should do it?
Well, basically the lack of any concrete type in this implementation is what troubles the compiler to figure out the
Entity.IDtype.This can be shown by not using a generic
Entitytype in yourStorageimplementation, like this:Solution 1: To help the compiler understand the
Entity.IDtype, you can conditionally conform to theDataStoreprotocol, by stating thatEntity.IDwill always be ofUUIDtype (which is actually what you want in your implementation):Solution 2: Even better, you can conditional constraint your
BaseEntityprotocol by stating thatIDwill always be ofUUIDtype. That way you do not need to change yourStorageimplementation:Solution 3: Another solution, which might be more appropriate in your context, is to convert
BaseEntityto a class. That way you also do not need to change yourStorageimplementation: