为什么 Swift 在将多个类型项放入数组时不对 Any 进行类型推断
Why Swift doesn't type inference to Any when put multiple type item in Array
使用Xcode7.1开发swift2.2时有两种情况让我很困惑,请看下面的例子,谢谢
首先,当导入Foundation时,我声明了一个包含两个项目的testArray,一个Integer类型1和一个String类型"hello",我的问题是为什么Swift类型推断testArray到Array(NSObject ) 而不是 Array(Any)
import Foundation
let testArray = [1, "hello"]
print(testArray.dynamicType) //testArray is Array<NSObject>
其次,当我删除 import Foundation 时,下面的代码无法编译,错误消息是 "Type of expression is ambiguous without more content",我的问题是为什么 Swift 不对 Array(Any) 进行类型推断这种情况,谢谢帮助
let testArray2 = [2, "world"]
print(testArray2)
//can't compile, error message = "Type of expression is ambiguous without more content"
因为它不会自动识别 Any
的数组
如果您将其定义为
,它将起作用
let testArray2 :[Any] = [2, "world"]
Foundation
库导入 NS API
,自动将 2
转换为 NSNumber
,将 "world"
自动转换为 NSString
,将其转换自动到 NSObject
数组
/// The protocol to which all types implicitly conform.
public typealias Any = protocol<>
Any
只是所有类型都隐式遵守的协议——它本身并不是具体类型。 Swift 无法推断出非具体类型的数组,这就是为什么它无法推断出 Any
,但成功推断出 NSObject
(Int
可以桥接到 NSNumber
, String
可以桥接到 NSString
– 它们都继承自 NSObject
,这是一个具体类型。
例如,考虑这个:
protocol Foo {}
struct Bar:Foo {}
struct Baz:Foo {}
let arr = [Bar(), Baz()] // error: Type of expression is ambiguous without more context
因为 Foo
是一个非具体类型,Swift 无法推断出它的数组。你必须明确地告诉编译器你想要它的类型是什么:
let arr:[Foo] = [Bar(), Baz()]
你也会得到与 AnyObject
相同的行为(因为它是所有 类 隐式遵守的协议——但仍然不是具体的类型):
class Qux {}
class Fox {}
let a = [Qux(), Fox()] // error: Type of expression is ambiguous without more context
let a1:[AnyObject] = [Qux(), Fox()] // no error
为什么 Swift 无法推断出非具体类型的数组很可能是由于语言中非具体类型的现有限制——目前大多数重要操作都需要具体类型。 .
但老实说,你真的应该多想想你是否实际上需要一个Any
的数组。我想不出有一个 Any
数组的实际应用,因为因为一切都隐含地符合元素,所以必须保证它们什么也不做(你不能对可能是任何东西的东西调用特定的方法).当然你可以进行类型转换,但是恢复你一开始就放弃的类型安全有什么意义呢?
您应该始终尽可能地特定类型。您可以为您的值构建一个包装器——这可以是一个简单的 struct
来包装几个属性,或者是一个 type erasure 以便将非具体类型包装在一个伪具体类型中。至少,您应该考虑创建自己的数组元素符合的协议。
使用Xcode7.1开发swift2.2时有两种情况让我很困惑,请看下面的例子,谢谢
首先,当导入Foundation时,我声明了一个包含两个项目的testArray,一个Integer类型1和一个String类型"hello",我的问题是为什么Swift类型推断testArray到Array(NSObject ) 而不是 Array(Any)
import Foundation
let testArray = [1, "hello"]
print(testArray.dynamicType) //testArray is Array<NSObject>
其次,当我删除 import Foundation 时,下面的代码无法编译,错误消息是 "Type of expression is ambiguous without more content",我的问题是为什么 Swift 不对 Array(Any) 进行类型推断这种情况,谢谢帮助
let testArray2 = [2, "world"]
print(testArray2)
//can't compile, error message = "Type of expression is ambiguous without more content"
因为它不会自动识别 Any
如果您将其定义为
,它将起作用let testArray2 :[Any] = [2, "world"]
Foundation
库导入 NS API
,自动将 2
转换为 NSNumber
,将 "world"
自动转换为 NSString
,将其转换自动到 NSObject
/// The protocol to which all types implicitly conform.
public typealias Any = protocol<>
Any
只是所有类型都隐式遵守的协议——它本身并不是具体类型。 Swift 无法推断出非具体类型的数组,这就是为什么它无法推断出 Any
,但成功推断出 NSObject
(Int
可以桥接到 NSNumber
, String
可以桥接到 NSString
– 它们都继承自 NSObject
,这是一个具体类型。
例如,考虑这个:
protocol Foo {}
struct Bar:Foo {}
struct Baz:Foo {}
let arr = [Bar(), Baz()] // error: Type of expression is ambiguous without more context
因为 Foo
是一个非具体类型,Swift 无法推断出它的数组。你必须明确地告诉编译器你想要它的类型是什么:
let arr:[Foo] = [Bar(), Baz()]
你也会得到与 AnyObject
相同的行为(因为它是所有 类 隐式遵守的协议——但仍然不是具体的类型):
class Qux {}
class Fox {}
let a = [Qux(), Fox()] // error: Type of expression is ambiguous without more context
let a1:[AnyObject] = [Qux(), Fox()] // no error
为什么 Swift 无法推断出非具体类型的数组很可能是由于语言中非具体类型的现有限制——目前大多数重要操作都需要具体类型。
但老实说,你真的应该多想想你是否实际上需要一个Any
的数组。我想不出有一个 Any
数组的实际应用,因为因为一切都隐含地符合元素,所以必须保证它们什么也不做(你不能对可能是任何东西的东西调用特定的方法).当然你可以进行类型转换,但是恢复你一开始就放弃的类型安全有什么意义呢?
您应该始终尽可能地特定类型。您可以为您的值构建一个包装器——这可以是一个简单的 struct
来包装几个属性,或者是一个 type erasure 以便将非具体类型包装在一个伪具体类型中。至少,您应该考虑创建自己的数组元素符合的协议。