我有一个[String]
let names = ["Joffrey", "Cersei", "Mountain", "Hound"]
我有一个函数,它采用[Any]
类型的数组。
func printItems(items: [Any]){
for item in items {
print(item)
}
}
现在当我用names
作为参数调用函数时,
printItems(names)
我收到错误无法使用类型为'([String])'的参数列表调用'printItems'。
Any
只是所有类型隐含符合的协议的typealias
。
思想?
答案 0 :(得分:2)
这是Swift的一个令人惊讶的限制。您无法转换数组以键入function string_shift(&$str){
$first_char = substr($str, 0, 1);
$str = substr($str, 1);
return $first_char;
}
,因此您无法将其传递给类型为[Any]
的函数。您可以使用[Any]
来投射数组的每个项目:
map
但是,在Swift中执行此操作的正确方法是使用Generics:
printItems(names.map {$0 as Any})
答案 1 :(得分:1)
虽然每个类型都符合Collections.sort( ... )
,但这与所有类型继承的通用隐式超类不同。
将类型转换为协议时,将创建具有不同结构的新值。因此,对于类型为Any
的字符串,需要从Any
表示进行物理转换:
String
到sizeof(String) // 24 bytes (on 64-bit, anyway)
表示:
Any
由于值类型直接保存在数组中,因此数组将是一个非常不同的形状,因此编译器必须完成相同的操作:
sizeof(Any) // 32 bytes, includes some meta data
// about what the type really is
Swift可能会为你自动化这个过程(如果你将一个变量传递给一个带names.map { $0 as Any } // create a new array, with the Any versions
的函数)。但我个人很高兴它没有,我宁愿这更明确 - 假设你的数组是巨大的,这将是隐含在幕后的很多处理。
这与你有一个引用类型数组不同,它们都是指向实际数据的指针,因此大小相同,并且在向上转换时不需要转换:
Any
所以说“这个class C { }
class D: C { }
let d = D()
let c: C = d
unsafeBitCast(d, UnsafePointer<Void>.self) // these value will
unsafeBitCast(c, UnsafePointer<Void>.self) // be the same
数组实际上是一个[D]
数组”只是编译器同意这些类型可以替换的问题,不需要进行数据转换:
[C]
但是当与类一起使用时,协议仍然与超类引用不同:
// so this works fine,
// no runtime transformation needed:
func f(cs: [C]) { }
let ds = [D(),D()]
f(ds)
答案 2 :(得分:0)
你需要明确地输入你的let声明 声明一个Any数组,而不是一个特定的类型数组。
使用您当前的声明,Swift会将其评估为[String]数组。 而不是[Any]数组。
要解决您的问题,请执行以下操作:
foo = fmap DTL.last $ DTLIO.readFile "../../../../etymwn.tsv
如果要保留let声明,请使用AnyObject 在你的printItems函数中,它将被Swift接受。
let names : [Any] = ["Joffrey", "Cersei", "Mountain", "Hound"]