如果与其一起使用的数组的类型为UInt,则以下Array扩展名会崩溃,但如果数组的类型为Int或String,则会起作用吗?
extension Array
{
func indexOf<T:Equatable>(value:T) -> Int?
{
for (i, val) in enumerate(self)
{
if (val as T == value)
{
return i;
}
}
return nil;
}
}
var a:[UInt] = [243, 234, 1, 212, 3, 56, 88, 11, 77];
var i = a.indexOf(234);
产生错误:
游乐场执行失败:错误:执行被中断,原因:EXC_BREAKPOINT(代码= EXC_I386_BPT,子代码= 0x0)。
该过程一直处于被中断的位置,使用“thread return -x”返回表达式求值之前的状态。
* thread#1:tid = 0x27a3c,0x00000001079d3f27 libswift_stdlib_core.dylib swift_dynamicCast + 1063, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
* frame #0: 0x00000001079d3f27 libswift_stdlib_core.dylib
swift_dynamicCast + 1063
帧#1:0x00000001137bbbc8
答案 0 :(得分:1)
问题是您定义的T: Equatable
与存储在数组中的T
无关。当您执行val as T
时,您将从数组值类型转换为需要等同的新本地T
。
当您使用文字调用indexOf
时,它不会被强制使用与a
中存储的类型相同的类型,因为该类型不会被您的扩展程序强制匹配。
最好使用函数来获取数组中对象的索引:
func indexOfObject<T : Equatable>(object: T, inArray collection: [T]) -> Int? {
var index : Int = 0
for testObject in collection {
if testObject == object {
return index
}
index++
}
return nil
}
严格强制T
类型等于且与传入的对象类型相匹配。
更好的是,你可能想要使用这样的扩展名:
extension Array {
func indexOfObjectPassingTest(test: (object: T) -> Bool) -> Int? {
var index : Int = 0
for object in self {
if test(object: object) {
return index
}
index++
}
return nil
}
}
更灵活,允许您这样做:
var i = a.indexOfObjectPassingTest({$0 == 234})
另请注意,我没有为我的方法定义T
,因为它已在数组本身中定义。