Swift泛型 vs Any

8

我在苹果官网上阅读了Swift文档。 其中有一个名为swapTwoValues的函数,可以交换任意给定的两个值。

func swapTwoValues1<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

现在我想编写类似的功能,但是不使用T泛型类型,而是使用Any。
func swapTwoValues2(_ a: inout Any, _ b: inout Any) {
    let temporaryA = a
    a = b
    b = temporaryA
}

要调用这些函数,我需要编写以下代码。
var a = 5
var b = 9


swapTwoValues1(&a, &b)

swapTwoValues2(&a, &b)

我有两个问题。

1) 为什么编译器会在第二个函数中给出这个错误(无法将不可变值作为inout参数传递:从'Int'到'Any'的隐式转换需要一个临时值)

2) 通用类型和Any之间有什么区别


2
  1. 泛型在编译时是强类型的:您可以将其与使用具体静态类型的任何实现进行比较。泛型只是让您避免手动复制每种类型(使用该方法)的实现:编译器将为您生成此重复功能。在您的第二个示例中,您回退到动态表示各种类型作为“任何”容器Any。编译器无法在编译时知道实际包含在ab中的具体类型是什么。
- dfrib
1
如果您传入一个String和一个Int,会发生什么?您如何想象在这种情况下进行交换? - luk2302
比较 https://dev59.com/rFoT5IYBdhLWcg3wjwB- 和 https://stackoverflow.com/q/44387949/2976878。 - Hamish
如果我不想交换两个值,只想调用那个函数怎么办?为什么编译器会报错? - Karen Karapetyan
因为简单来说:你有一个 Int,但想将它作为 Any 指针传递给方法,这会丢失类型信息 - 你想要传递指针 / inout 的唯一原因是你想要从函数内部设置其值。而出于已经给出的原因,这是不可能的。 - luk2302
显示剩余3条评论
1个回答

13

Any与泛型无关,它只是Swift中的一种类型,可用于表示任何类型的实例,包括函数类型(请参见官方文档)。因此,您可以将任何类型的实例转换为Any。但是,当使用特定类型的Any时,如果您想访问特定于子类的函数/属性,则必须将Any实例强制转换回实际类型。

在使用泛型时,不涉及转换。泛型允许您实现一个函数,该函数适用于满足类型约束的所有类型(如果指定任何),但在对特定类型调用函数时,它实际上将与特定类型一起工作,而不是与非特定类型如Any一起工作。

通常,对于这种问题,使用泛型是更好的解决方案,因为泛型在编译时具有强类型,而上下转型发生在运行时。


哪种类型继承自 Any? - Karen Karapetyan
根据官方文档,_Any可以表示任何类型的实例,包括函数类型。_ - Dávid Pásztor
是的,但这并不意味着大多数标准类型都继承自Any。 - Karen Karapetyan
它们可以转换为Any,这是与您的问题相关的事情,但是您是正确的,我没有足够精确,因此我已更新我的答案。 - Dávid Pásztor
2
@KarenKarapetyan Any顶级类型。它是所有类型的超类型,因此所有类型都是它的子类型。 - Hamish
3
正如@Hamish所写的那样,“Any”可以被视为顶级类型,但从Swift 3开始,它已经实现并记录为内置关键字(请参见https://stackoverflow.com/questions/45324315/where-is-any-declared-implemented-in-swift-3-and-onwards),这意味着继承在此处并不严格适用(而是强大的“可表示性”),而是“Any”是一个独立定义的实体。 - dfrib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接