当我们像这样进行可选链接时
var myVar: Int?
if let unwrapped = myVar {
}
编译器将unwrapped
视为Int
我有符合特定协议的类数组。考虑示例:
import Foundation
protocol SomeProtocol: class {}
class A {}
extension A: SomeProtocol {}
class B {}
extension B: SomeProtocol {}
class C {}
extension C: SomeProtocol {}
let arr: [SomeProtocol] = [A(), B(), C()]
arr.forEach{ object in
if object is A {
// object is treated like SomeProtocol, not like A class
}
}
我可以做(object as! A)
,但这看起来很丑。如何找到一种将协议项智能转换为班级变量的方法?
答案 0 :(得分:3)
通过可选的绑定,您处在正确的路径上。
as?
是as!
的一种变体,其求值类型为您要投射到的类型的可选。您可以将其与可选绑定结合使用:
arr.forEach{ object in
if let a = object as? A { // (object as? A) is of type "A?", but we are unwrapping it
// a is of type A now
}
}
答案 1 :(得分:2)
您可以使用case let
对其进行清理。以上面的示例为例,可以将其更改为
protocol SomeProtocol: class {}
class A {}
extension A: SomeProtocol {}
class B {}
extension B: SomeProtocol {}
class C {}
extension C: SomeProtocol {}
let arr: [SomeProtocol] = [A(), B(), C()]
for case let object as A in arr {
print("item is A")
}
这将循环遍历数组,如果可以将项目强制转换为指定的类型,则将执行for循环的主体。尽管它最终与上面的Sweeper答案相同,但它只是删除了一条嵌套线并看上去更加干净。
答案 2 :(得分:2)
在switch
语句中使用模式匹配
如果要在同一循环中处理多个类型,则使用带有模式匹配的switch
来建立类型很方便:
示例:
protocol SomeProtocol: class {}
class A {
let foo = 17
}
extension A: SomeProtocol {}
class B {
let bar = "hello"
}
extension B: SomeProtocol {}
class C {
let baz = true
}
extension C: SomeProtocol {}
class D: SomeProtocol {}
let arr: [SomeProtocol] = [D(), A(), C(), B()]
for object in arr {
switch object {
case let a as A:
print("object is A")
print(a.foo)
case let b as B:
print("object is B")
print(b.bar)
case let c as C:
print("object is C")
print(c.baz)
default:
print("object is some other type")
}
}
输出:
object is some other type object is A 17 object is C true object is B hello