2

我在 swift 中玩了一些代码,遇到了一个有趣的案例。让我们从一个小序言开始:假设您创建了一些可选变量:

let a: String? = "abcd"; let b: Int? = 4
print(
    "Type of \(a) is \(type(of: a))" //Type of Optional("abcd") is Optional<String>
    "Type of \(b) is \(type(of: b))", //Type of Optional(4) is Optional<Int>
    separator: "\n"
)

然后你强制解开这样的类型au并且bu不是可选的。

let au = a!; let bu = b!
print(
    "Type of \(au) is \(type(of: au))", //Type of abcd is String
    "Type of \(bu) is \(type(of: bu))", //Type of 4 is Int

    au + String(bu), //abcd4
    separator: "\n"
)

看起来很合理,但是当您尝试将相同的代码应用于Optional<Any>

let a: Any? = "abcd"; let b: Any? = 4
let au = a!; let bu = b!
print(
    "Type of \(a) is \(type(of: a))", //Type of Optional("abcd") is Optional<Any>
    "Type of \(b) is \(type(of: b))", //Type of Optional(4) is Optional<Any>
    "Type of \(au) is \(type(of: au))", //Type of abcd is String
    "Type of \(bu) is \(type(of: bu))", //Type of 4 is Int
    //au + String(bu),
    separator: "\n"
)

但是现在如果你尝试做同样的连接au + String(bu),swift 会产生编译错误,即使这两个变量已知是某种具体的类型,正如 swift 本身所报告的那样。错误是:

error: protocol type 'Any' cannot conform to 'LosslessStringConvertible' because only concrete types can conform to protocols

这当然看起来像一个错误,不是吗。请分享您的意见。

4

3 回答 3

3

正如其他人所指出的,type(of:)它是值的动态运行时类型。编译器仅依赖于静态的、可证明的值类型。在上面的代码中,编译器唯一可以证明的是它au的类型是 Any。符合 Any 的众多类型之一是 String,但编译器并不知道在所有可能的代码路径中,值真的是 String。

由于没有func + (Any, String)重载,因此无法编译。

请注意,这Any?是一种奇异而危险的类型。它的问题不是这个示例的原因,但它与 Optional 提升交互的方式可能会导致严重的歧义和混乱。Swift 中的每种类型都可以隐式提升为该类型的 Optional。Swift 中的每种类型都可以隐式转换为 Any。结合这两个事实意味着Any可以隐式提升为Any?、 或Any??、 或Any???等,但所有这些也是 的子类型Any。这会造成各种微妙的头痛。你应该强烈避免使用Any; 它很少是正确的工具。但是你应该更加小心允许Any?出现在你的代码中。这表明可能出现了问题。

于 2019-11-27T14:37:15.517 回答
1

type(of: T) 返回值的动态类型。

您可以使用该type(of:)函数查找值的动态类型,特别是当动态类型与静态类型不同时。值的 静态类型是该值的已知编译时类型。值的 动态类型是值在运行时的实际类型,可以是其具体类型的子类型。

此解释取自上述type(of: T)函数的注释。在 Xcode 中执行 Cmd+单击type(of: T)以阅读更多内容

于 2019-11-27T13:37:55.607 回答
1

type(of: T) 方法获取任何变量的运行时类型。这就是为什么您将 (type(of: au) 视为 String 的原因。但出于安全原因,Swift 不允许隐式类型转换。这就是您不能在 Swift 中添加 Int 和 Double 而不进行转换的原因。您需要显式转换你的代码工作。

于 2019-11-27T13:23:39.617 回答