带有类型别名的协议不能以这种方式使用。Swift无法直接谈论诸如
ValidationRule或的元类型
Array。您只能处理类似
ValidationRulewhere...或的实例
Array<String>。使用typealiases,无法直接到达那里。因此,我们必须通过类型擦除间接到达那里。
Swift有几个类型擦除器。
AnySequence,
AnyGenerator,
AnyForwardIndex,等等,这些都是协议的仿制版本。我们可以建立自己的
AnyValidationRule:
struct AnyValidationRule<InputType>: ValidationRule { private let validator: (InputType) -> Bool init<base: ValidationRule where base.InputType == InputType>(_ base: base) { validator = base.validate } func validate(input: InputType) -> Bool { return validator(input) }}这里的深奥魔力是
validator。可能还有其他方法可以不关闭而进行类型擦除,但这是我所知道的最好方法。(我也讨厌Swift无法将
validate其作为闭包属性来处理。在Swift中,属性获取器不是正确的方法。因此,您需要额外的间接层
validator。)
有了它,您可以制作所需的数组类型:
let len = ValidationRuleLength()len.validate("stuff")let cond = ValidationRuleCondition<String>()cond.validate("otherstuff")let rules = [AnyValidationRule(len), AnyValidationRule(cond)]let passed = rules.reduce(true) { $0 && $1.validate("combined") }请注意,类型擦除不会放弃类型安全性。它只是“擦除”实现细节的一层。
AnyValidationRule<String>与仍然不同
AnyValidationRule<Int>,因此将失败:
let len = ValidationRuleLength()let condInt = ValidationRuleCondition<Int>()let badRules = [AnyValidationRule(len), AnyValidationRule(condInt)]// error: type of expression is ambiguous without more context



