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

时间:2017-03-13 01:26:01

标签: swift protocols factory swift-protocols

我正在考虑我的应用程序中的验证检查,我认为在任何模型上调用ValidatorFactory,实现Validee,意味着说哪个类负责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)

为什么?

1 个答案:

答案 0 :(得分:1)

如果您遇到的问题是编译错误,则需要修改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 {

    }
}