Как я могу использовать тип протокола в сигнатуре метода? - PullRequest
2 голосов
/ 15 января 2020

У меня есть такая функция:

// 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
}

Как я могу использовать это с коллекцией типов?

В идеале, если у меня есть конформеры:

struct ModelA: FetchableRecord { }
struct ModelB: FetchableRecord { }

тогда я бы хотел иметь возможность:

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)'"
}

По крайней мере, я хотел бы понять, почему это невозможно. Спасибо.

1 Ответ

3 голосов
/ 15 января 2020

Причиной ошибки является FetchableRecord.Type, равное , а не , такое же, как ModelA.Type или ModelB.Type. Даже если обе структуры соответствуют протоколу FetchableRecord, ограничение моделей (в соответствии с определенным протоколом) не влияет на «типы», технически говоря:

ModelA.self == FetchableRecord.self ИЛИ ModelB.self == FetchableRecord.self false.

Чтобы решить эту проблему, вы можете реализовать сигнатуру метода следующим образом:

func fetch(for theType: FetchableRecord.Type) -> [FetchableRecord] {
    // ...
}

, поэтому ваш код:

let modelTypes: [FetchableRecord.Type] = [ModelA.self, ModelB.self]
modelTypes.forEach {
    fetch(for: $0)
}

должен работать , На этом этапе вы имеете дело с этим «Гетерогенно» вместо «Гомогенно».

Кроме того, если это делает его более разумным, обратите внимание, что при вызове метода fetch согласно вашей реализации, это:

enter image description here

тип параметра FetchableRecord.Protocol. Однако, согласно вышеупомянутой реализации (в этом ответе), это:

enter image description here

тип параметра FetchableRecord.Type, который является хотел результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...