在Swift中使用协议类型强制转换异常
在处理类及其子类的实例时,我遇到了一种似乎是强制转换异常的情况,这两种类型都是作为类所遵循的协议键入的 由于我不想用我的领域的细节来复杂化这个问题,我在下面给出了一个人工例子来说明这个看似问题的存在在Swift中使用协议类型强制转换异常,swift,casting,protocols,Swift,Casting,Protocols,在处理类及其子类的实例时,我遇到了一种似乎是强制转换异常的情况,这两种类型都是作为类所遵循的协议键入的 由于我不想用我的领域的细节来复杂化这个问题,我在下面给出了一个人工例子来说明这个看似问题的存在 protocol P { func canCast(_ p: P) -> Bool } extension P { func canCast(_ p: P) -> Bool { return p as? Self != nil } } clas
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()
由于Y
是X
的一个子类,我们应该能够将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
我错过什么了吗
return p as? Self != nil
与
return p as? P != nil
根据@meggar发布的答案,我做了更多的工作,发现在这种情况下,
Self
总是表示符合协议的类型,而不是它的任何子类,无论该方法是在符合协议的类的实例上调用还是在它的任何子类上调用
所以在这种情况下,
return p as? Self != nil
与
return p as? X != nil
对于X
的实例以及X
的任何子类的实例,此强制转换将成功,这就是问题中提出的两种情况下返回true
的原因
为了证明这一点,我在协议扩展的方法体中添加了一行,以打印self
的类型以及self
表示的类型。我还创建了一个新类Z
,它是Y
的子类
下面给出了完整的修改代码,这表明Self
继续表示X
,而不管该方法是在X
、Y
还是Z
(在每种情况下都是Self
的类型)的实例上调用的
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