Reputation: 1415
I have a function like this:
// A generic function that can fetch values from the store given a type
// Corresponds to a table and it's rows
func fetch<T: FetchableRecord>(for theType: T.Type) -> [T] {
// ... fetch from a store using the type
// This compiles fine
}
How can I use this with a collection of types?
Ideally, if I have some conformers:
struct ModelA: FetchableRecord { }
struct ModelB: FetchableRecord { }
then I would like to be able to do:
let modelTypes: [FetchableRecord.Type] = [ModelA.self, ModelB.self]
modelTypes.forEach {
fetch(for: $0) // xxx: does not compile: "Cannot invoke 'fetch' with an argument list of type '(for: FetchableRecord.Type)'"
}
At the very least, I would like to figure why this would not be possible. Thank you.
Upvotes: 2
Views: 65
Reputation: 31695
The reason for the error is FetchableRecord.Type
is not the same as ModelA.Type
or ModelB.Type
. Even if both of the structs conform to FetchableRecord
protocol, constraining the models (by conforming to a certain protocol) does not affect the "Types", more technically speaking:
ModelA.self == FetchableRecord.self
OR ModelB.self == FetchableRecord.self
is false
.
In order to resolve this issue, you could implement the method's signiture as:
func fetch(for theType: FetchableRecord.Type) -> [FetchableRecord] {
// ...
}
therefore, your code:
let modelTypes: [FetchableRecord.Type] = [ModelA.self, ModelB.self]
modelTypes.forEach {
fetch(for: $0)
}
should work. At this point, you are dealing with it "Heterogeneously" instead of "Homogeneously".
Furthermore, if that makes it more sensible, note that when calling fetch
method as per your implementation, it is:
the parameter type is FetchableRecord.Protocol
. However, as per the above-mentioned implementation (in this answer), it is:
the parameter type is FetchableRecord.Type
, which is the wanted result.
Upvotes: 3