Как упражнение в обучении, я переписываю свой validation library в Свифт.Как добавить в коллекцию различные типы, соответствующие протоколу с ассоциированным типом?
У меня есть ValidationRule
протокол, который определяет, что отдельные правила должны выглядеть следующим образом:
protocol ValidationRule {
typealias InputType
func validateInput(input: InputType) -> Bool
//...
}
Соответствующий тип InputType
определяет тип входа быть подтверждено (например: String). Он может быть явным или общим.
Вот два правила:
struct ValidationRuleLength: ValidationRule {
typealias InputType = String
//...
}
struct ValidationRuleCondition<T>: ValidationRule {
typealias InputType = T
// ...
}
В другом месте, у меня есть функция, которая проверяет вход с коллекцией ValidationRule
с:
static func validate<R: ValidationRule>(input i: R.InputType, rules rs: [R]) -> ValidationResult {
let errors = rs.filter { !$0.validateInput(i) }.map { $0.failureMessage }
return errors.isEmpty ? .Valid : .Invalid(errors)
}
Я думал, что это будет работать, но компилятор не согласен.
В следующем примере, даже если входной сигнал является String, rule1
«s InputType
является String, и rule2
s InputType
является строка ...
func testThatItCanEvaluateMultipleRules() {
let rule1 = ValidationRuleCondition<String>(failureMessage: "message1") { $0.characters.count > 0 }
let rule2 = ValidationRuleLength(min: 1, failureMessage: "message2")
let invalid = Validator.validate(input: "", rules: [rule1, rule2])
XCTAssertEqual(invalid, .Invalid(["message1", "message2"]))
}
... Я получаю очень полезно сообщение об ошибке:
_ не конвертируется в ValidationRuleLength
, который является загадочным, но предполагает, что типы должны быть точно равны?
Так что мой вопрос ... как добавить различные типы, все они соответствуют протоколу с ассоциированным типом в коллекцию?
Не знаете, как добиться того, что я пытаюсь, или если это возможно?
EDIT
Вот это без контекста:
protocol Foo {
typealias FooType
func doSomething(thing: FooType)
}
class Bar<T>: Foo {
typealias FooType = T
func doSomething(thing: T) {
print(thing)
}
}
class Baz: Foo {
typealias FooType = String
func doSomething(thing: String) {
print(thing)
}
}
func doSomethingWithFoos<F: Foo>(thing: [F]) {
print(thing)
}
let bar = Bar<String>()
let baz = Baz()
let foos: [Foo] = [bar, baz]
doSomethingWithFoos(foos)
Здесь мы получаем:
Протокол Foo может быть использован только в качестве общего ограничения, поскольку он имеет Атман или связанных типов.
Я понимаю это. Что мне нужно сказать, это примерно то, что:
Какую версию Swift вы используете? – matt
Я использую самую последнюю версию Swift 2 –
Что такое ValidationResult? Пожалуйста, предоставьте код, который я могу воспроизвести. – matt