And*_* H. 15 casting protocols swift
有一个协议:
protocol Valuable {
func value() -> Int
}
Run Code Online (Sandbox Code Playgroud)
和一个实现协议的类:
class Value: Valuable {
private let v: Int
init(value: Int) {
v = value
}
func value() -> Int {
return v
}
}
Run Code Online (Sandbox Code Playgroud)
有一个Value对象数组存储在Any类型的变量中:
let any: Any = [Value(value: 1), Value(value: 2), Value(value: 3)]
Run Code Online (Sandbox Code Playgroud)
可以将Any转换为[Value]:
let arrayOfValue = any as? [Value] // [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
为什么不能将[任何]归咎于[有价值]?
let arrayOfValuable = any as! [Valuable] // compiler error BAD INSTRUCTION
let arrayOfValuable2 = any as? [Valuable] // nil
Run Code Online (Sandbox Code Playgroud)
更新:在Swift3中完全可以强制[Any]
转换为[Valuable]
.只要阵列中的所有元素都可以投射,演员阵容就会成功; 否则演员会失败.
var strings: [Any] = ["cadena"]
var mixed: [Any] = ["cadena", 12]
strings as! [String] // ["cadena"]
mixed as? [String] // nil
mixed as! [String] // Error! Could not cast value...
Run Code Online (Sandbox Code Playgroud)
此前作为斯威夫特2:要制作[Valuable]
出来的[Any]
,必须手动像函数来完成map
其他的答案已经解释.
目前Swift中没有与泛型相关的协方差或逆变(从Swift 2开始).这意味着不同类型的数组(如[String]
或[UIView]
)不能相互转换,也不能比较它们的类型.
[UIView]
并且[UIButton]
彼此之间没有层次结构,无论它UIButton
是否为子类UIView
.这就是为什么即使以下返回true:
Valuable.self is Any.Type // true
Run Code Online (Sandbox Code Playgroud)
由于同样的原因,以下转换产生错误:
var anyArray: [Any] = ["cadena"]
anyArray as! [String] // BAD_INSTRUCTION error
"some string" as! Double // BAD_INSTRUCTION error
Run Code Online (Sandbox Code Playgroud)
这两个分支没有任何关系,并且演员阵容是不可能的,因为这as!
是一个强制演员,它会引发错误.
这个对我有用:
let arrayOfValuable = arrayOfValue?.map { $0 as Valuable }
Run Code Online (Sandbox Code Playgroud)
或相同:
let arrayOfValuable2 = (any as? [Value])?.map { $0 as Valuable }
Run Code Online (Sandbox Code Playgroud)
总之,arrayOfValuable
应该具有以下类型[Valuable]?
编辑:
或者试试这个:
let arrayOfAny: [Any] = [Value(value: 1), Value(value: 2), Value(value: 3)]
let arrayOfValuable3 = arrayOfAny.map { $0 as Valuable }
Run Code Online (Sandbox Code Playgroud)
当然,更好的方法是声明arrayOfAny
为[Valuable]
,这样以后就不会出现问题了。