gpt4 book ai didi

generics - 如何在 Swift 中调用不明确的泛型函数?

转载 作者:IT王子 更新时间:2023-10-29 05:49:25 26 4
gpt4 key购买 nike

我定义了两个泛型函数

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)

当然 Swift 会提示并抛出错误
“工作”的用法不明确
这是可以理解的,因为我不清楚我是想使用Comparable还是Hashable(Int都符合它们)

有什么方法可以提示编译器我想使用哪个?

最佳答案

这是不明确的,因为 Int都是HashableComparable ,并且这两个协议(protocol)都不在同一层次结构中。 (您可以查看 Int protocol hierarchy on Swifter 。)

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'

由于每个协议(protocol)的相关类型要求,您不能明确地告诉它调用哪个函数,但是您可以做的是定义第三个函数:

func f<T: Comparable where T: Hashable>(t: T) {
println("Both Hashable & Comparable: \(t)")
}
f(number)
// Both Hashable & Comparable: 5

这就是Swift implements ..<运算符,否则对于同时实现 Comparable 的类型来说将是不明确的和 ForwardIndexType .


为了进一步扩展,这里看看我所说的“由于每个协议(protocol)的相关类型要求,你不能明确地告诉它调用哪个函数”是什么意思。协议(protocol)可以用作类型,如 Swift 书中所述 chapter on Protocols :

protocol RandomNumberGenerator {
func random() -> Double
}

class Dice {
let generator: RandomNumberGenerator
// ...
}

在此示例中,生成器属性可以是任何符合 RandomNumberGenerator 的类型- 类似于id<ProtocolName>在 Objective-C 中使用。但是,当协议(protocol)不包含关联类型或引用时,它们只能用作类型 Self在他们的声明中。不幸的是,这几乎排除了 Swift 中的所有内置类型,包括 HashableComparable .

Hashable继承自 Equatable , 其中引用 Self在定义 == 时运算符(operator):

func ==(lhs: Self, rhs: Self) -> Bool

Comparable对其运算符做同样的事情:

func <=(lhs: Self, rhs: Self) -> Bool
// similar definitions for <, >, and >=

这些协议(protocol)只能用作通用约束,而不能用作声明变量时的类型。 (据我所知,这是没有记录的,但可以通过错误消息发现。)

没有该限制的两个协议(protocol)是 PrintableBooleanType ,所以我们可以看看它们是如何工作的。 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使用 as 的特定协议(protocol)关键字,并以这种方式调用特定的通用函数:

p(t as Printable)
// Printable: true

p(t as BooleanType)
// BooleanType: true

因此只要我们有一个限定协议(protocol),我们就可以选择调用泛型方法的哪个变体。

关于generics - 如何在 Swift 中调用不明确的泛型函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26108325/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com