Swift 通用协议函数参数

Swift Generic Protocol Function Parameters

这似乎对我有用。我想要做的就是让 Rule 协议能够 performRule 在采用该规则协议的任何结构上,然后 return 一个布尔值。但是,按照我的代码目前的方式,我无法访问 performRule(:value) value 参数上的任何属性。我觉得我错过了一个重要的概念或者有问题。您应该能够将下面的代码复制到 playground 中以亲自查看问题。

import Foundation

protocol NumberCalculation {
    var number : NSNumber { get set }
}

protocol Rule {
    var invalidMessage : String { get set }
    func performRule<T>(value: T) -> Bool
}

struct GreaterThanRule : Rule, NumberCalculation  {
    var invalidMessage: String
    var number : NSNumber

    init(valueMustBeGreaterThan value: NSNumber, withInvalidMessage message : String = "") {
        number = value
        invalidMessage = message
    }

    func performRule<NSNumber>(value: NSNumber) -> Bool {
        number.decimalValue // works 
        value.decimalValue // doesn't work
        return true
    }
}

<NSNumber> 在您的 performRule(value:) 方法中定义了一个新的通用占位符类型,正如您将其命名为 NSNumber,它将影响 Foundation 的 NSNumber class – 表示 value: 参数是 your 通用占位符类型,而不是 Foundation 的 NSNumber.

如果您希望符合 Rule 的类型可以为 performRule(value:) 方法的参数选择自己的类型 – 那么您需要一个 associated type,而不是通用占位符.

protocol NumberCalculation {
    var number : NSNumber { get set }
}

protocol Rule {

    // define associated type that conforming types must satisfy
    // by providing a type to replace it with
    associatedtype Value
    var invalidMessage : String { get set }
    func performRule(value: Value) -> Bool
}

struct GreaterThanRule : Rule, NumberCalculation {

    var invalidMessage: String
    var number : NSNumber

    init(valueMustBeGreaterThan value: NSNumber, withInvalidMessage message : String = "") {
        number = value
        invalidMessage = message
    }

    // satisfy associated type implicitly by annotating the type of the parameter
    // as NSNumber – the compiler will infer that Value == NSNumber.
    func performRule(value: NSNumber) -> Bool {
        number.decimalValue // works
        value.decimalValue // also works!
        return true
    }
}