首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Swift中调用模糊的泛型函数?

如何在Swift中调用模糊的泛型函数?
EN

Stack Overflow用户
提问于 2014-09-29 20:29:52
回答 1查看 3.8K关注 0票数 9

我定义了两个泛型函数

代码语言:javascript
复制
func job<T: Comparable>(x: T) {
  println("1")
}

func job<T: Hashable>(x: T) {
  println("2")
}

当我试图给其中之一打电话时,例如:

代码语言:javascript
复制
let myInt: Int = 1 // Explicit Int just for clarity of the example
job(myInt)

当然,斯威夫特抱怨并抛出一个错误

模糊使用“作业”

这是可以理解的,因为不清楚我是要使用可比较的 one还是Hashable (Int符合两者的要求)。

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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-29 20:50:08

这是模棱两可的,因为Int既是Hashable又是Comparable,这两个协议都不是同一层次结构。(您可以查看Int 更快的协议层次。)

代码语言:javascript
复制
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'

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

代码语言:javascript
复制
func f<T: Comparable where T: Hashable>(t: T) {
    println("Both Hashable & Comparable: \(t)")
}
f(number)
// Both Hashable & Comparable: 5

这就是Swift工具 ..<操作符的用法,否则对于实现ComparableForwardIndexType的类型来说,它是不明确的。

为了进一步扩展,下面是我所说的“您不能显式地告诉它要调用哪个函数,因为每个协议的相关类型要求”。协议可以用作类型,如Swift书关于议定书的章节中所述

代码语言:javascript
复制
protocol RandomNumberGenerator {
    func random() -> Double
}

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

在本例中,生成器属性可以是任何符合RandomNumberGenerator的类型,类似于在Objective中使用id<ProtocolName>的方式。但是,只有在声明中不包括关联类型或引用Self时,协议才能用作类型。不幸的是,这排除了Swift中几乎所有内置类型,包括HashableComparable

Hashable继承自Equatable,在定义==运算符时引用Self

代码语言:javascript
复制
func ==(lhs: Self, rhs: Self) -> Bool

Comparable对其运算符也是这样做的:

代码语言:javascript
复制
func <=(lhs: Self, rhs: Self) -> Bool
// similar definitions for <, >, and >=

这些协议只能用作泛型约束,在声明变量时不能用作类型。(据我所知,这是无文档的,但可以通过错误消息发现。)

没有这种限制的两个协议是PrintableBooleanType,所以我们可以看看它们是如何工作的。Bool是唯一符合BooleanType的内置类型,也是Printable,所以这将是我们的测试类型。下面是我们的泛型函数p()和变量t --注意,和前面一样,我们不能只使用t调用函数

代码语言:javascript
复制
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转换为特定的协议,并以这种方式调用特定的泛型函数:

代码语言:javascript
复制
p(t as Printable)
// Printable: true

p(t as BooleanType)
// BooleanType: true

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

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26108325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档