首先,当导入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时,下面的代码无法编译,错误信息是“表达式的类型没有更多内容”,我的问题是为什么Swift在这种情况下没有对Array(Any)进行类型推断,谢谢求助
let testArray2 = [2,"world"] print(testArray2) //can't compile,error message = "Type of expression is ambiguous without more content"
/// 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无法推断出非具体类型的数组很可能是由于语言中非具体类型的现有限制 – 目前大多数非平凡操作都需要具体类型. See this great Q&A for an example.
但说实话,你应该更多地思考你是否真的需要一个Any数组.我想不出有一个Any数组的单一实际应用,因为因为一切都隐含地符合元素,所以必须保证它们什么都不做(你不能在可能是任何东西的东西上调用特定的方法).当然你可以打字,但是重新开始你扔掉的类型安全有什么意义呢?
您应始终尽可能地具体类型.您可以为您的值构建一个包装器 – 这可以是一个简单的结构来包装几个属性,或者是一个type erasure,以便将非具体类型包装在伪具体类型中.至少,您应该考虑创建自己的数组元素符合的协议.