Swift类型推理在这里是否自相矛盾?

时间:2014-08-24 21:08:31

标签: xcode swift xcode6 swift-playground xcode6-beta6

这是我的测试代码:

var myDict: [String: AnyObject] = ["k":"v"]

var a = myDict["k"]
var b = a as String

var c = myDict["k"] as String

这是我在Xcode6-beta6中的Swift游乐场:

Playground

根据类型推断的规则,并不抱怨c逻辑上与b抱怨不抱怨?

3 个答案:

答案 0 :(得分:2)

我相信这是一个错误。这里发生的部分原因是String不是一个对象。如果您将第一行更改为:

var myDict: [String: Any] = ["k":"v"]
然后一切都很好。因此,如果字符串不是对象,则将AnyObject?类型的变量强制转换为String应该会产生错误。并且,由于编译器已经确定a属于AnyObject?类型,因此应该抱怨将a投射到String

请注意,如果您将最后一行更改为:

var c = myDict["k"] as NSString

错误消失了,支持这个问题是String不是一个对象。如果您将Int作为数组中的值并尝试将其转换为Int,则会得到相同的投诉。

<强>更新

因此情节变浓。如果您没有import Foundation或导入导入Foundation的内容,则会出现其他错误。没有基金会:

enter image description here

很明显,其中一些与String s作为非对象和NSString作为对象的双重性质以及使用String作为{{1}的能力有关导入NSString时的情况。

答案 1 :(得分:1)

这与Dictionary 两个下标重载的事实有关:

subscript (key: Key) -> Value?
subscript (i: DictionaryIndex<Key, Value>) -> (Key, Value) { get }

第一个是熟悉的,你传递一个键,它给你一个可选的值;您可以使用它来设置键的值。

第二个不太常见。我相信DictionaryIndex是字典中的一种迭代器,你可以用它作为下标来直接获取该迭代器的键值对。

当编译器找不到匹配的重载时(在这种情况下,第一个不匹配,因为它返回一个可选的,不能转换为非可选的String),它只是随意挑选一个(好吧,无论如何,这对我来说似乎是武断的)来显示错误。在这个地方,它会选择你不认识的第二个。这就是为什么这个错误对你来说很奇怪。

答案 2 :(得分:0)

这很有效。

var c = myDict["k"] as AnyObject! as String   // "v"

要回答你的问题,Swift抱怨的原因可能是你试图一次性完成这两次转换。请记住,语句var a = myDict["k"]已包含隐式转换。隐含转换为AnyObject?,因此上述内容也可以这样:

var c = myDict["k"] as AnyObject? as String   // "v"

请注意,如果未定义键"k",则上述操作会导致运行时错误。您可以通过转换为nil来允许此返回String?