问题
This seems like it should work to me. All I am trying to do is make the Rule protocol able to performRule on whatever struct adopts that Rule protocol and then return a boolean. However, with the way my code is currently I cannot access any properties on the performRule(:value) value parameter. I feel like I am missing an important concept or something is buggy. You should be able to copy the code below into a playground to see the issue for yourself.
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
}
}
回答1:
Saying <NSNumber> defines a new generic placeholder type in your performRule(value:) method, which, as you've named it NSNumber, will shadow Foundation's NSNumber class – meaning that the value: parameter is of type your generic placeholder, not Foundation's NSNumber.
If you want it so that types conforming to Rule can choose their own type for the parameter of the performRule(value:) method – then you want an associated type, not a generic placeholder.
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
}
}
来源:https://stackoverflow.com/questions/40442497/swift-generic-protocol-function-parameters