我可以写一些简短有效的代码示例:
var array = ["one","two"];
var name = array[0];
一切都好。没有错误。 name
现在包含one
。
现在假设我写道:
var array = ["one","two"];
var name = array["0"];
它将成为一个错误,并明确原因:数组不是字典,我应该通过索引访问它。
但为什么错误说“类型 Int
不符合协议ExtendedGraphemeClusterLiteralConvertible
?
为什么Int
,如果是[String]
?
var array = ["one":0,"two":1];
var name = array[0];
很明显:“类型DictionaryIndex<String, Int>
不符合协议IntegerLiteralConvertible
”
答案 0 :(得分:2)
该错误消息是因为您提供字符串文字,而不是String
类型的实例,编译器期望Int
(因为那&#39} ; Array
的下标方法接受的内容。编译器 将字符串文字转换为类型Int
的实例的方式是使用StringLiteralConvertible
或ExtendedGraphemeClusterLiteralConvertible
协议中的方法,因此它会检查查看Int
类型是否符合其中之一。由于Int
不符合,您会收到您正在查看的错误消息。
这解释了Daniel T的其他信息:
var array = ["one","two"]
array["0"] // trying to convert string literal to Int
var foo: Int = "0" // trying to convert string literal to Int
var index = "0"
array[index] // trying to convert String instance to Int
同样,您的最后一个示例显示编译器尝试相同的事情 - 尝试将整数文字转换为DictionaryIndex<String, Int>
的实例,因为Dictionary
实例&#39; s下标可以传递给该词典的一个实例Key
类型或一个DictionaryIndex<Key, Value>
。
答案 1 :(得分:1)
subscript
的{p> Array
:
struct Array<T> : MutableCollectionType, Sliceable {
//...
subscript (index: Int) -> T
期望Int
作为索引。如果你这样做:
array["0"]
这是错误的,因为"0"
不是Int
。但是,换句话说,如果"0"
可以是Int
,那就没问题。
在这里,"0"
是什么在Swift?它的字符串,但实际上是ExtendedGraphemeClusterLiteral
。 Swift有两种字符串文字类型,ExtendedGraphemeClusterLiteral
和StringLiteral
。
""
empty→StringLiteral "A"
只有一个字符→ExtendedGraphemeClusterLiteral "AB"
两个或多个字符→StringLiteral 无论如何,在Playground尝试这个:
extension Int: ExtendedGraphemeClusterLiteralConvertible {
typealias ExtendedGraphemeClusterLiteralType = String
public init(unicodeScalarLiteral value: String) {
self = value.toInt() ?? 0
}
public init(extendedGraphemeClusterLiteral value: String) {
self = value.toInt() ?? 0
}
}
var array = ["one","two"];
var name = array["0"]; // -> "one"
&#34;输入&#39; Int&#39;不符合协议&#39; ExtendedGraphemeClusterLiteralConvertible&#39;&#34;意味着...
编译器:&#34;如果Int
符合ExtendedGraphemeClusterLiteralConvertible
,我可以编译它!&#34;
答案 2 :(得分:0)
有趣的是,如果你这样做:
var array = ["one","two"];
var index = "0"
var name = array[index];
错误将是'String' is not convertible to 'Int'
。
我认为这是因为系统试图将"0"
转换为Int,这意味着要进行大量的协议检查。 Array的索引类型可以转换为Self.Index,这是一个ForwardIndexType ......好吧,事情变得很奇怪。
而Swift对隐式变量类型转换有强有力的规则。因此,如果您使用变量作为索引,则更清楚。
请注意,var foo: Int = "0"
会产生与array["0"]
相同的错误。