Created
April 3, 2018 05:42
-
-
Save creaaa/3e59bced287e829ff7ec02f11b67d251 to your computer and use it in GitHub Desktop.
悩ましい
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
class Man {} | |
class SuperMan: Man {} | |
let m = Man() | |
let n = m as! SuperMan // これは当然無理だ。わかる。だが | |
*/ | |
let m = Optional.some(42) | |
let n = m as! Int // なんでこのサブタイピング関係は通るんだァァァァ!!!!! | |
print(n) // 42 |
Optional.some(42) as! Int が成功するという、
本来のサブタイプ関係からすれば奇妙すぎる計算が可能な理由は、
「Optional型だけに認められた、コンパイラによる特別扱い」という理解で、ひとまず悪くはないのではないか、と思う。
まさか...と思って、
let a: [Animal] = []
a as! [Cat]
やったら....やっぱこれも成功した。これもOptionalの場合と同じくらいキモい。
だって、Animal() as! Cat は当然死ぬんだぞ。Arrayの型パラになった瞬間セーフになるのは元来ちょっとおかしな話で。
...でも、
let a = String as! [Bool] も成功した。これまじどうなってんだよwww
// なんか [] が表示されない、ここ。おかしい。editで見てみて
Dog as! [Animal] だろうが、
Dog as! [Int] だろうが、やりたい放題。
とにかく、Arrayにも「コンパイラによる特別扱い」がされているのは間違いない。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
なんとなく、わかってきた気がする。
答えは、「そうでないと、不都合だから」。
・map()メソッドを考えてみる。
mapとは、「箱から中身を出さずに、箱に入れたまま値に対して演算を可能にする」メソッド。
で、実装は、こうなってる。
let a: Int? = 42 、といったとき、
たとえその中身は本来Int型だといっても、Int?型 の演算ができるような仕組みになっていないとダメなんだ。
つまり、変数の中身のオブジェクトの型(本来の型)だけに着目するだけではダメで、
変数の型にも気を配る必要がある。
つまり、サブタイピングなプログラミングとは、全体としては「2つの型が同居している」状態。
大半のケースでは、中身の型は意識せず、変数の型だけに注目していればよい(∵変数の型が、呼び出せるメソッドやプロパティ、その他演算すべて)のだが、
is や as(?, !) など、型チェックが絡んできた場合のみ、そのインスタンスの型が何だったか、思い出す必要がある