there are two situation make me confuse when develop swift 2.2 by using Xcode 7.1, please see the example below, thanks
First, when import Foundation, I declared an testArray which contains two item, an Integer type 1 and a String type "hello", my question is why Swift type inference testArray to Array(NSObject) instead of Array(Any)
import Foundation
let testArray = [1, "hello"]
print(testArray.dynamicType) //testArray is Array<NSObject>
Second, when i remove import Foundation, the code below can't be compile, the error message is "Type of expression is ambiguous without more content", my question is why Swift not type inference to Array(Any) in this situation, thanks for help
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
is just a protocol that all types implicitly conform to – it's not a concrete type itself. Swift cannot infer an array of non-concrete types, which is why it fails to infer Any
, but succeeds with NSObject
(Int
can be bridged to NSNumber
, String
can be bridged to NSString
– and they both inherit from NSObject
, which is a concrete type).
For example, consider this:
protocol Foo {}
struct Bar:Foo {}
struct Baz:Foo {}
let arr = [Bar(), Baz()] // error: Type of expression is ambiguous without more context
Because Foo
is a non-concrete type, Swift cannot infer an array of it. You have to explicitly tell the compiler what you want its type to be:
let arr:[Foo] = [Bar(), Baz()]
You'll also get the same behaviour with AnyObject
(as it's a protocol that all classes implicitly conform to – but still not a concrete type):
class Qux {}
class Fox {}
let a = [Qux(), Fox()] // error: Type of expression is ambiguous without more context
let a1:[AnyObject] = [Qux(), Fox()] // no error
Why Swift is unable to infer an array of non-concrete types is most likely due to the existing limitations of non-concrete types in the language – currently concrete types are required for most non-trivial operations. See this great Q&A for an example.
But to be honest, you should really be thinking more about whether you actually need an array of Any
. I cannot think of a single practical application of having an array of Any
, as because everything implicitly conforms to the elements, they must be guaranteed to do nothing (you can't call a specific method on something that could be anything). Sure you can type-cast, but what's the point in getting back the type safety that you threw away to begin with?
You should always be as type specific as you can. You could build a wrapper for your values – this could either be a simple struct
to wrap a couple of properties, or a type erasure in order to wrap non-concrete types in a pseudo concrete type. At the very least, you should consider creating your own protocol that your array elements conform to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With