Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save creaaa/97f834fb7a5288d5f7d9f25434be31da to your computer and use it in GitHub Desktop.
Save creaaa/97f834fb7a5288d5f7d9f25434be31da to your computer and use it in GitHub Desktop.
let a: Int? = 42
let b = a as! Int // 成功するか??? => した
print(b) // 42
// コンパイラの解決パターン
Int to Optional<Int> is [value-to-optional]
// つまりこれ...暗黙の型変換「じゃな」くない...???
// だって、元の情報、失われてないのだから...
// ただし、ジェネリクス型が絡んできてるので、また事情が違うのかもしれない...
// とりあえず、俺はひとまず 暗黙の型変換「じゃない」って立場をとっとくわ。
// すなわちこれは、「ただの親子関係」、Int が 親クラスたる Int? として振る舞ってるだけ、
// って考えといたほうが一貫性ある。いまんとこ。
// ...待って、前言撤回...
let c = Optional.some(42)
let d = c as! Int // ...え??? 成功する...
print(d) // 42. なんで...
// コンパイラの解決パターン
Optional<Int> to Optional<Int> is [deep equality]
// もちろん、パターンマッチも行ける...DATO.....
switch c {
case let no as Int:
print(no.description) // マッチ
default: break
}
☆ 4/1時点での結論としては、
「サブタイピングは実行時の型強制に置き換えられる」
from https://qiita.com/ukitaka/items/8bcff4348c79d820ba32
俺なりの理解だと、インスタンスは、親クラス型の変数に格納されると、『半分アップキャストされ、半分は元の型のまま、みたいな形』になり、
親クラスと子クラスの狭間で、どちらでも取れるようなふるまいをする。
だから、親クラスの型の変数に代入できるし、
だから、as!とかすると元の子クラスに戻ることに成功するし、上のように case as で子クラスの型にマッチする。
// let f: Int = c // ただし、もちろん相変わらずこれはできない...
// これは通常の親-子クラスの振る舞いと同じなので全く正常であるし、そもそもこれできたらnull安全が崩壊する
// 謎深まった。。。
/*
2/27時点での結論。
1. やっぱりこれは、暗黙の型変換 「ではない」。インスタンスは依然 Int? 型である。
2. ただし、「"ある程度"Int型としても振る舞うことができる」 Int? 型 である。
【ある程度】の範囲
○ => as? / as! / キャストパターンによるパターンマッチ
...むしろ、let a: Int? = 42 のときではなく、
(ここは"本当に何も"起こってない。ただの親クラスへの代入)
let c = Optional.some(42) のときに、
Int への暗黙の型変換が行われてる、と考えたほうが自然じゃね???
fだって、c is Int が true になるし。
いきなり、親クラスが子クラスとみなされることは通常ありえへんぞ。
*/
// 続報が入り次第追って報告する。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment