首页 > 解决方案 > swift中的协议继承和结构

问题描述

我想创建一个Validatable具有两个属性的协议:一个validator和一个isAbleToProceed布尔值:

protocol Validatable {
    var validator: Validator { get set }
    var isAbleToProceed: Bool { get set }
}

我想定义不同类型的Validators(出生日期验证器、电子邮件验证器等)。为此,我创建了一个工厂:

protocol Validator {}

struct ValidatorFactory {
    internal static let sharedInstance = ValidatorFactory()

    func dateOfBirthValidator(minimumAge: Int, maximumAge: Int) -> DateOfBirthValidator {
        return DateOfBirthValidator(minimumAge: minimumAge, maximumAge: maximumAge)
    }

    func driversLicenseValidator(minLicenseDuration: Int) -> DriversLicenseValidator {
        return DriversLicenseValidator(minLicenseDuration: minLicenseDuration)
    }
}

这是 DateOfBirthValidator 的实现:

struct DateOfBirthValidator: Validator {
    let minimumAge: Int
    let maximumAge: Int

    func isDateOfBirthValid(date: Date) -> Bool {
        if let age = Calendar.current.dateComponents([.year], from: date, to: Date()).year {
            return (minimumAge ... maximumAge).contains(age)
        } else {
            return false
        }
    }
}

然后我会有一个类 ViewController 来实现 Validatable 协议:

class ViewController: Validatable {

    // MARK: Internal Properties

    internal var validator: DriversLicenseValidator
    internal var isAbleToProceed: Bool = false

}

但是编译器会报告 ViewController 不符合Validatable(没有验证器)

如果我创建Validator一个超类并且所有验证器结构都变成类并从中继承,这可以解决。但是有没有办法让它与结构和协议一起工作?

标签: swiftstruct

解决方案


这个问题几乎与您的问题重复,除了它询问为什么不能通过协议一致性满足 get-only 属性。答案是,理论上它可以,但现在你不能。这有几个 Swift 错误

现在,在您的情况下,您有一个 get/set 属性(至少正如在协议中声明的那样;您let在实现中实现了它)。

由于 Liskov 替换原则,我应该可以说:

var someValidatable = ViewController() as Validatable
someValidateable.validator = SocialSecurityValidator()

如果你能够做你想做的事,这将失败有两个原因:

  1. validator具有更受限制的访问权限,let而不是var
  2. SocialSecurityValidator无法分配A ,validator因为它属于类型DriversLicenseValidator

推荐阅读