我定义了两个泛型函数
func job<T: Comparable>(x: T) {
println("1")
}
func job<T: Hashable>(x: T) {
println("2")
}当我试图给其中之一打电话时,例如:
let myInt: Int = 1 // Explicit Int just for clarity of the example
job(myInt)当然,斯威夫特抱怨并抛出一个错误
模糊使用“作业”
这是可以理解的,因为不清楚我是要使用可比较的 one还是Hashable (Int符合两者的要求)。
有什么方法可以提示编译器我想使用哪一个?
发布于 2014-09-29 20:50:08
这是模棱两可的,因为Int既是Hashable又是Comparable,这两个协议都不是同一层次结构。(您可以查看Int 更快的协议层次。)
func f<T: Hashable>(t: T) {
println("Hashable: \(t)")
}
func f<T: Comparable>(t: T) {
println("Comparable: \(t)")
}
let number = 5
f(number)
// error: ambiguous use of 'f'由于每个协议的相关类型要求,您不能显式地告诉它要调用哪个函数,但是您可以定义第三个函数:
func f<T: Comparable where T: Hashable>(t: T) {
println("Both Hashable & Comparable: \(t)")
}
f(number)
// Both Hashable & Comparable: 5这就是Swift工具 ..<操作符的用法,否则对于实现Comparable和ForwardIndexType的类型来说,它是不明确的。
为了进一步扩展,下面是我所说的“您不能显式地告诉它要调用哪个函数,因为每个协议的相关类型要求”。协议可以用作类型,如Swift书关于议定书的章节中所述
protocol RandomNumberGenerator {
func random() -> Double
}
class Dice {
let generator: RandomNumberGenerator
// ...
}在本例中,生成器属性可以是任何符合RandomNumberGenerator的类型,类似于在Objective中使用id<ProtocolName>的方式。但是,只有在声明中不包括关联类型或引用Self时,协议才能用作类型。不幸的是,这排除了Swift中几乎所有内置类型,包括Hashable和Comparable。
Hashable继承自Equatable,在定义==运算符时引用Self:
func ==(lhs: Self, rhs: Self) -> BoolComparable对其运算符也是这样做的:
func <=(lhs: Self, rhs: Self) -> Bool
// similar definitions for <, >, and >=这些协议只能用作泛型约束,在声明变量时不能用作类型。(据我所知,这是无文档的,但可以通过错误消息发现。)
没有这种限制的两个协议是Printable和BooleanType,所以我们可以看看它们是如何工作的。Bool是唯一符合BooleanType的内置类型,也是Printable,所以这将是我们的测试类型。下面是我们的泛型函数p()和变量t --注意,和前面一样,我们不能只使用t调用函数
func p<T: Printable>(t: T) {
println("Printable: \(t)")
}
func p<T: BooleanType>(t: T) {
println("BooleanType: \(t)")
}
let t: Bool = true
p(t)
// error: Ambiguous use of 'p'相反,我们需要使用t关键字将(upcast?) as转换为特定的协议,并以这种方式调用特定的泛型函数:
p(t as Printable)
// Printable: true
p(t as BooleanType)
// BooleanType: true因此,只要我们有一个合格的协议,我们就可以选择要调用的泛型方法的哪个变体。
https://stackoverflow.com/questions/26108325
复制相似问题