Swift 带有类型化的协议。协议只能用作通用约束

Swift Protocols with Typealises. Protocol can only be used as a generic constraint

我在考虑我的应用程序中的验证检查,我认为在实现 Validee 的任何模型上调用 ValidatorFactory,这意味着 class 负责 ValidatorCreation 听起来不错。但是下面的代码不起作用:(

代码:

struct Client: Validee {
    typealias ValidatorFactoryClass = ClientValidator
}

protocol Validee {
    associatedtype ValidatorFactoryClass: AbstractValidatorFactory
}

protocol Validator {
    func validate() throws -> Void
}

protocol AbstractValidatorFactory {
    associatedtype Model
    static func create(fromModel model: Model) -> Validator
}

struct ValidatorFactory {
    static func createValidator(fromModel model: Validee) -> Validator {
        return model.ValidatorFactoryClass.create(fromModel: model)
    }
}

struct ClientValidator : AbstractValidatorFactory {
    typealias Model = Client

    static func create(fromModel model: Model) -> Validator {
        return ClientDeliveryAddressValidator(withModel: model)
    }
}

struct ClientDeliveryAddressValidator: Validator {
    typealias Model = Client
    let client: Client

    init(withModel client: Client) {
        self.client = client
    }

    func validate() throws {

    }
}

let client = Client()
do {
    try ValidatorFactory.createValidator(fromModel: client).validate()
} catch {
    // error handling here
}

但即使我忘记了 Validator Factory 并尝试 运行 以下代码也不起作用:

client.ValidatorFactoryClass.create(fromModel: client)

为什么?

如果您遇到的问题是由于编译错误,您的 ValidatorFactory 结构需要修改。

您不能直接将协议用作类型。您将它用作类型的约束。这意味着不是将 Validee 作为 ValidatorFactory.createValidator 的参数类型,而是对该类型的约束。此更改将为您提供:

struct ValidatorFactory<T:Validee> {
    static func createValidator(fromModel model: T) -> Validator {
        return model.ValidatorFactoryClass.create(fromModel: model)
    }
}

这仍然有问题,因为Swift无法计算出类型T和调用create的参数类型之间的关系。但是这种关系存在于您的代码中;你只需要明确说明即可。

ValidatorFactory 更改为这个为我编译。但是,我还没有尝试 运行 代码。

struct ValidatorFactory<T:Validee> {
    static func createValidator(fromModel model: T) -> Validator {
        return T.ValidatorFactoryClass.create(fromModel: model as! T.ValidatorFactoryClass.Model)
    }
}

编辑:

鉴于 Validee 已经知道工厂,更改设计会更简单,因此 Validee 知道直接创建验证器。

这会给你:

protocol Validee {
    static func create(fromModel model: Self) -> Validator
}

protocol Validator {
    func validate() throws -> Void
}

struct ValidatorFactory<T:Validee> {
    static func createValidator(fromModel model: T) -> Validator {
        return T.create(fromModel: model)
    }
}

struct Client: Validee {
    static func create(fromModel model: Client) -> Validator {
        return ClientDeliveryAddressValidator(withModel: model)
    }
}

struct ClientDeliveryAddressValidator: Validator {
    typealias Model = Client
    let client: Client

    init(withModel client: Client) {
        self.client = client
    }

    func validate() throws {

    }
}