在Swift中将协议强制转换为类

时间:2019-10-02 09:52:34

标签: swift

当我们像这样进行可选链接时

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),但这看起来很丑。如何找到一种将协议项智能转换为班级变量的方法?

3 个答案:

答案 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