swift 如何通过协议继承使关联类型的泛型协议不泛型?

jaql4c8m  于 2023-04-04  发布在  Swift
关注(0)|答案(2)|浏览(166)

我有一个泛型协议和相关的类型,在某些时候我想让它不泛型。同样的行为在类中工作得很好,但不幸的是,我不能在协议中使用同样的逻辑。例如,这是绝对好的:

class Validator<Value> {
    func validate(_ value: Value?) -> String? {
        return nil
    }
}

class StingValidator: Validator<String> {
}

class EmptyStringValidator: StingValidator {
    override func validate(_ value: String?) -> String? {
        return ((value?.isEmpty ?? true) == true) ? "Empty" : nil
    }
}

func anyfunc() {
    let validator: StingValidator = EmptyStringValidator()
}

但使用协议时,我收到编译错误
协议“StringValidatorProtocol”只能用作泛型约束,因为它具有Self或关联类型要求

protocol ValidatorProtocol {
    associatedtype Value
    func validate(_ value: Value?) -> String?
}

protocol StringValidatorProtocol: ValidatorProtocol where Value == String {
}

struct EmptyStringValidator: StringValidatorProtocol {
    func validate(_ value: String?) -> String? {
        return ((value?.isEmpty ?? true) == true) ? "Empty" : nil
    }
}

func anyfunc() {
    let validator: StringValidatorProtocol = EmptyStringValidator()
}

有什么想法吗?有什么方法可以使通用协议不通用吗?我将感谢任何帮助!

db2dz4w8

db2dz4w81#

使一个协议与非泛型的关联类型是不可能的,我认为你需要的是更多的泛型:

func anyfunc() {
    let validator: StringValidatorProtocol = EmptyStringValidator()
}

对于自由函数,你不能做你想做的事情,但是在类或结构中:

protocol ValidatorProtocol {
    associatedtype Value
    init()
    func validate(_ value: Value?) -> String?
}

protocol StringValidatorProtocol: ValidatorProtocol where Value == String {
}

class EmptyStringValidator: StringValidatorProtocol {
    required init() {
        
    }
    func validate(_ value: String?) -> String? {
        return value?.isEmpty ?? true ? "Empty" : nil
    }
}

class MyClass<Validator: ValidatorProtocol> {
    static func validate(_ string: Validator.Value?) -> String? {
        let validator: Validator = Validator()
        return validator.validate(string)
    }
}
MyClass<EmptyStringValidator>.validate("Hello World") // nil
MyClass<EmptyStringValidator>.validate("") // "Empty"
MyClass<EmptyStringValidator>.validate(nil) // "Empty"
h7appiyu

h7appiyu2#

我不知道“使它不通用”是什么意思,但如果这对你来说还不够,请通过编辑让我们知道:
你所显示的错误可以用一个不透明的常量来解决。

let validator: some StringValidatorProtocol = EmptyStringValidator()

相关问题