Swift func с универсальным выражением where - это протокол, который сам соответствует - PullRequest
0 голосов
/ 22 февраля 2019

Я пытаюсь написать статический обобщенный метод, который принимает протокол в качестве аргумента и регистрирует экземпляр класса в контейнере Swinject в качестве разрешения протокола.Важно, чтобы я не мог зарегистрировать модуль в качестве протокола, которому он не соответствует.

Я написал что-то вроде этого:

/// RegisterableModule guarantee that conformer has `create()` method returning self

public extension RegisterableModule {

    static func registerModule<P>(asProtocol proto: P.Type,
                                  in container: Container) {
        container.register(proto, name: nil) { (resolver) -> P in
            return self.create()
        }
    }
}

Он не компилируется, потому что, очевидно, Self может не соответствоватьв P

Я также попытался указать общее ограничение, используя where:

  1. where Self: P делает ошибку компиляции "Тип" Self ", ограниченный непротокольным, не классовым типом'P' '
  2. where self: P делает ошибку множественной компиляции.
  3. where Self: P.Type делает ошибку компиляции "Тип" Self "ограничен не протоколом, не классом типа" P.Type "«
  4. where self: P.Type делает несколько ошибок компиляции.

Мне также интересно, могу ли я указать ограничение, что P может быть только протоколом.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

К сожалению, в Swift (пока) нет способа определить требование соответствия универсальным параметрам или требовать, чтобы параметр был протоколом.

Именно по этой причине Swinject's API переадресации типов не является безопасным типом .Существует «трюк» , который позволяет выразить требование соответствия, однако я не уверен, будет ли это практичным для вашего варианта использования:

extension RegisterableModule {

    static func registerModule<P>(
        asProtocol proto: P.Type, 
        in container: Container, 
        typeCheck: (Self) -> P
    ) {
        container.register(proto) { _ in self.create() as! P }
    }
}

MyModule.registerModule(
    asProtocol: MyProtocol.self, 
    in: container, 
    typeCheck: { $0 }
)
0 голосов
/ 22 февраля 2019

Можете ли вы попробовать, я только что добавил P: SomeProtocol

public extension RegisterableModule {

    static func registerModule<P:SomeProtocol>(asProtocol proto: P.Type,
                                  in container: Container) {
        container.register(proto, name: nil) { (resolver) -> P in
            return self.create()
        }
    }
}
...