упрощенная версия моего кода, который показывает проблему:Ограничить ассоциированный тип
protocol Transformer {
typealias Input
typealias Output
func transform(s: Input) -> Output
}
protocol InputType {}
protocol OutputType {}
extension Int: OutputType {}
extension String: InputType {}
struct StringToInt: Transformer {
typealias Input = String
typealias Output = Int
func transform(s: Input) -> Output {
return s.characters.count
}
}
typealias Transform = InputType -> OutputType
func convert<T: Transformer where T.Input == InputType, T.Output == OutputType>
(transformer: T) -> Transform {
return transformer.transform
}
convert(StringToInt()) // error: Cannot invoke 'convert' with an argument list of type '(StringToInt)'
Я предполагаю, что ошибка происходит потому, что компилятор не может достичь в StringToInt
и убедитесь, что Input
и Output
действительно соответствуют InputType
и OutputType
соответственно.
Для меня лучшим способом решить эту проблему было бы ограничение связанных типов непосредственно в протоколе. Это было бы более выразительно, и у компилятора была бы больше информации. Но просто делать typealias Input: InputType
не работает.
Есть ли способ ограничить связанный тип?
Но если заменить возвращение тип 'convert()' будет 'InputType -> OutputType' вместо' Input -> Output', он больше не работает. Зачем? – mschumacher
Потому что 'transform' is' Input -> Output' не 'InputType -> OutputType'. Вы не можете обрабатывать протоколы как обычные типы в Swift большую часть времени. Однако это не является причиной ошибки здесь. Посмотрите на это изображение для деталей. http://milen.me/images/writings/swift-generic-protocols/swift-protocols-two-worlds.png – mustafa