raheel
raheel

Reputation: 1415

How can I use a protocol's type in method signature?

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

Answers (1)

Ahmad F
Ahmad F

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:

enter image description here

the parameter type is FetchableRecord.Protocol. However, as per the above-mentioned implementation (in this answer), it is:

enter image description here

the parameter type is FetchableRecord.Type, which is the wanted result.

Upvotes: 3

Related Questions