Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save creaaa/91118fdd2ca08ff782359157bd0fc3e9 to your computer and use it in GitHub Desktop.
Save creaaa/91118fdd2ca08ff782359157bd0fc3e9 to your computer and use it in GitHub Desktop.
気をつけて
class Animal {}
class Cat: Animal {
func pero() {}
}
let animals: [Animal] = [Cat()]
/* これ、ふつーにいけると思いきや。。。アウト!!
まぁでも、そらそうか。
すなわち...
「一旦親クラスの変数に格納してしまうと、インスタンスの型情報は失われる」
*/
// let cat: Cat = animals[0] // コンパイルエラー!
let cat = animals[0] // これは通る。型は Animal に推論される。
// 一旦、インスタンスの型情報が失われてしまったら、
// as? か as! か キャストパターンのパターンマッチ に 賭けてみるしかないのだ。
// let cat2 = animals[0] as! Cat ← まぁ今回はそりゃ成功するけど、バリバリ型安全から外れてる
/*
結論
インスタンスを、親クラスの変数に格納し、一旦親クラスとして扱ってしまうと、
インスタンスの型情報は失われる。(内部ではちゃんと残ってるから、↓のようにas! できるんだが)
復活させるには、as? / as! / パターンマッチ に賭けてみるしかなくなるので、
型安全からは少し離れた気になってくるので注意しる。
*/
// 型パターン の if case, めっちゃ書きにくいww
// = の 左側は case ○○, 右側は switch ×× が来る、
// という一貫性に基づいているので我慢しろ!!
if case let cat as Cat = animals[0] {
print(cat.pero()) // cat は Cat型として扱えるため、Cat#メソッド が呼べる
}
// 次のgist は これを踏まえ、 T と T? の関係に迫る。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment