Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save creaaa/3e59bced287e829ff7ec02f11b67d251 to your computer and use it in GitHub Desktop.
Save creaaa/3e59bced287e829ff7ec02f11b67d251 to your computer and use it in GitHub Desktop.
悩ましい
/*
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
@creaaa
Copy link
Author

creaaa commented Apr 11, 2018

なんとなく、わかってきた気がする。
答えは、「そうでないと、不都合だから」。

・map()メソッドを考えてみる。
mapとは、「箱から中身を出さずに、箱に入れたまま値に対して演算を可能にする」メソッド。
で、実装は、こうなってる。

let a: Int? = 42 、といったとき、
たとえその中身は本来Int型だといっても、Int?型 の演算ができるような仕組みになっていないとダメなんだ。

つまり、変数の中身のオブジェクトの型(本来の型)だけに着目するだけではダメで、
変数の型にも気を配る必要がある。
つまり、サブタイピングなプログラミングとは、全体としては「2つの型が同居している」状態。
大半のケースでは、中身の型は意識せず、変数の型だけに注目していればよい(∵変数の型が、呼び出せるメソッドやプロパティ、その他演算すべて)のだが、
is や as(?, !) など、型チェックが絡んできた場合のみ、そのインスタンスの型が何だったか、思い出す必要がある

@creaaa
Copy link
Author

creaaa commented Apr 11, 2018

Optional.some(42) as! Int が成功するという、
本来のサブタイプ関係からすれば奇妙すぎる計算が可能な理由は、
「Optional型だけに認められた、コンパイラによる特別扱い」という理解で、ひとまず悪くはないのではないか、と思う。

@creaaa
Copy link
Author

creaaa commented Apr 11, 2018

まさか...と思って、

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