Come esercizio di apprendimento sto riscrivendo il mio validation library in Swift.Come si aggiungono tipi diversi conformi a un protocollo con un tipo associato a una raccolta?
Ho un protocollo ValidationRule
che definisce quali regole individuali dovrebbe essere simile:
protocol ValidationRule {
typealias InputType
func validateInput(input: InputType) -> Bool
//...
}
Il tipo associato InputType
definisce il tipo di ingresso da convalidare (per esempio String). Può essere esplicito o generico.
Qui ci sono due regole:
struct ValidationRuleLength: ValidationRule {
typealias InputType = String
//...
}
struct ValidationRuleCondition<T>: ValidationRule {
typealias InputType = T
// ...
}
Altrove, ho una funzione che convalida un ingresso con una collezione di ValidationRule
s:
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)
}
ho pensato che questo stava andando al lavoro, ma il compilatore non è d'accordo.
Nell'esempio che segue, anche se l'input è una stringa, rule1
s' InputType
è una stringa, e rule2
s InputType
è una stringa ...
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"]))
}
... sto diventando estremamente messaggio di errore utile:
_ non è convertibile in ValidationRuleLength
che è criptico ma suggerisce che i tipi dovrebbero essere esattamente uguali?
Quindi la mia domanda è ... come posso aggiungere tipi diversi che sono tutti conformi a un protocollo con un tipo associato in una raccolta?
Non sei sicuro di come ottenere ciò che sto tentando o se è addirittura possibile?
EDIT
Ecco è senza contesto:
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)
Qui abbiamo:
protocollo Foo può essere utilizzato solo come un vincolo generico, perché ha Sé o requisiti di tipo associati.
Lo capisco. Quello che devo dire è qualcosa di simile:
doSomethingWithFoos<F: Foo where F.FooType == F.FooType>(thing: [F]) {
}
Quale versione di Swift stai usando? – matt
Sto usando l'ultimissimo Swift 2 –
Che cos'è un ValidationResult? Si prega di fornire il codice _enough in modo che io possa riprodurre_. – matt