2017-12-01 5 views
0

クラスとそのサブクラスのインスタンスを操作するときに、キャスト異常と思われるものが発生しています。どちらもクラスが準拠しているプロトコルとして型指定されています。Swiftのプロトコルタイプで異常をキャストする

私のドメインの特質に問題を複雑にしたくないので、私は以下に見える問題を示す人工的な例を示しました。

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のサブクラスであるので、我々はXbをキャストすることができるはずですが、我々はYaをキャストすることはできないはずです。

、以下に示すように、これは、正常に動作します:私は、プロトコルで宣言さ.canCast()メソッドを使用する場合

print(a as? Y != nil) // prints false 
print(b as? X != nil) // prints true 

はしかし、キャストの両方が成功したように表示されます。

print(b.canCast(a))  // prints true 
print(a.canCast(b))  // prints true 

私は何かが足りません?

答えて

0

と同じですが、私はいくつかのより多くの仕事をしたし、このような状況でSelfは常にプロトコルに準拠タイプを表していることを発見し、メソッドが準拠しているクラスのインスタンスかそのサブクラスのいずれかで呼び出されているかどうかにかかわらず、そのサブクラスのどれもではありません。

したがって、この場合には、

return p as? Self != nil 

は、このキャストは、なぜtrueある、Xのインスタンスだけでなく、Xのいずれかのサブクラスのインスタンスのために成功します

return p as? X != nil 

と同じです質問に提示された両方のケースで返されます。

これを証明するために、のタイプとSelfで表されるタイプを印刷するために、プロトコル拡張のメソッド本体に行を追加しました。また、Yのサブクラスである新しいクラスZを作成しました。

完全な変更されたコードはSelfに関係なく方法は(それぞれの場合においてselfのタイプである)XY又はZのインスタンス上で呼び出されているかどうかのXを表現し続けることを示しており、以下に与えられます。

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 
1
return p as? Self != nil 

が@meggarによって投稿答えに続き

return p as? P != nil 
関連する問題