在Swift中使用协议类型转换异常

时间:2017-12-01 15:15:35

标签: swift casting protocols

在处理类及其子类的实例时,我遇到的似乎是一个强制转换异常,它们都被类型化为类符合的协议。

由于我不想将问题与我的域名的具体内容复杂化,我在下面给出了一个人为的例子来说明看似问题。

protocol P {
    func canCast(_ p: P) -> Bool
}

extension P {
    func canCast(_ p: P) -> Bool {
        return p as? Self != nil
    }
}

class X: P {}
class Y: X {}

let a: P = X()
let b: P = Y()

由于YX的子类,我们应该能够将b投射到X,但我们无法将a投射到Y print(a as? Y != nil) // prints false print(b as? X != nil) // prints true

这很好,如下所示:

.canCast()

但是,当我使用协议中声明的print(b.canCast(a)) // prints true print(a.canCast(b)) // prints true 方法时,两个强制转换似乎都成功了:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.example.com|www2\.example.com [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/support/?$ http://example.com/site1/page1.html [R=301,NC,L]

我错过了什么吗?

2 个答案:

答案 0 :(得分:1)

return p as? Self != nil

相同
return p as? P != nil

答案 1 :(得分:0)

继@meggar发布的答案后,我做了一些工作,发现在这种情况下Self始终表示符合协议的类型,而不是任何子类,无论方法是否在符合类或其任何子类的实例上调用。

因此,在这种情况下,

return p as? Self != nil 

相同
return p as? X != nil

对于X的实例以及X的任何子类的实例,此转换将成功,这就是在问题中显示的两种情况下都返回true的原因。

为了证明这一点,我在协议扩展中向方法主体添加了一行,以打印self的类型以及Self所代表的类型。我还创建了一个新类Z,它是Y的子类。

下面给出了完整修改后的代码,其中显示Self继续代表X,无论是XYZself(在每种情况下都是protocol P { func canCast(_ p: P) -> Bool } extension P { func canCast(_ p: P) -> Bool { print("Type of self: \(type(of: self)), Self represents: \(Self.self)") return p as? Self != nil } } class X: P {} class Y: X {} class Z: Y {} let a: P = X() let b: P = Y() let c: P = Z() print(a.canCast(b)) // Type of self: X, Self represents: X // true print(b.canCast(a)) // Type of self: Y, Self represents: X // true print(c.canCast(a)) // Type of self: Z, Self represents: X // true 的类型)。

let results : Results