【问题标题】:Swift Generics vs AnySwift 泛型与任何
【发布时间】:2025-12-10 10:00:02
【问题描述】:

我在苹果网站上阅读了 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) Generic 类型和 Any 有什么区别

【问题讨论】:

  • 2) 泛型在编译时是强类型的:您可以将其与使用具体静态类型的任何实现进行比较。泛型只是让您避免手动复制每种类型(使用该方法)的实现:编译器将为您生成这种复制的功能。在您的第二个示例中,您依靠动态将各种类型表示为“任何东西”-容器Any。编译器无法在编译时知道您的 ab 实现中实际包含的具体类型。
  • 如果传入StringInt 会发生什么? 您认为在这种情况下如何进行交换?
  • 如何解决编译器错误?
  • 思考上面的@luk2302:s 评论,然后问自己为什么你甚至想要一个交换函数来处理两个类型为Any 的参数(因为唯一的用例是两个参数实际上“包装”相同的具体类型:但如果通用方法完全涵盖这种情况)。

标签: swift generics any anyobject inout


【解决方案1】:

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

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

一般来说,对这类问题使用泛型是一个更好的解决方案,因为泛型在编译时是强类型的,而向上/向下转换是在运行时发生的。

【讨论】:

  • 哪种类型继承自 Any ?
  • 根据official documentationAny可以表示任何类型的实例,包括函数类型。
  • 是的,但这并不意味着大多数标准类型都继承自 Any。
  • @KarenKarapetyan Anytop type。它是所有类型的超类型,因此所有类型都是它的子类型。
  • 正如@Hamish 所写,Any 可以被认为是*类型,但在 Swift 3 中,it is implemented and documented as a builtin keyword,这意味着继承在这里并不严格起作用(而是全能的 "representability by"),而是Any 是一个定义明确的生物。