我当时正在快速处理一些代码,并遇到了一个有趣的案例。让我们从一些前言开始:假设您创建了一些可选变量:
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
这肯定看起来像是个错误,不是吗。请分享您的意见。
type(of:T)方法获取任何变量的运行时类型。这就是为什么您看到(type(of:au)as String。但是出于安全原因,Swift不允许隐式类型转换。这就是为什么您不能在Swift中不进行转换就不能添加Int和Double的原因。您需要为您的代码可以正常工作。
type(of: T)
返回值的动态类型。
[正如其他人指出的,type(of:)
是值的动态运行时类型。编译器仅依赖于值的静态可证明类型。在上面的代码中,编译器唯一可以证明的是au
的类型为Any。符合Any的许多类型之一是String,但是编译器并不知道在所有可能的代码路径中,值实际上都是String。