型を明確にすることがSwiftらしいやり方であると気づいた時、同時に時には型を消す必要があると分かります。この講演では、型とは何か、型を消すことが何を意味するか、なぜそうしたいかについて解説します。
型消去の話をします
- 怖い?
- どういうこと?
- 型とは何?
最高の定義はWikipediaで見つかりました。型とは、分類であり、値の集合とその値に対する有効な演算を定義するものであるということですね。
Swiftコンパイラにとってこれらは便利な考え方です。
StringにIntを入れることは有効ではないわけです。しかしすべての型が平等なのではなく、コンパイラがチェック出来ない型が有ります。
ここで具象型と抽象型を考えます。具象型はダイレクトにインスタンス化でき、明確なデータを持っていて、オブジェクト間でやりとしして情報共有がなされます。
一方抽象型は不完全な実装になります。ダイレクトにインスタンス化出来なくて、振る舞いを表すものになります。抽象型がオブジェクトを表す時、格納される値よりも挙動が重要になります。ここにジェネリクスでType T と U を使って定義したものがあります。
SwiftはTがなにか、Uがなにかわかっていません。こういう時にどうしたらいいのか。抽象型をどうやったら具象化出来るのか。Type reflection (型反映) というのが役に立ちます。抽象型をプレースホルダに入れていくということです。皆さん使っているTypeParamater(型パラメータ)です。
StringやIntがパラメータに渡されてインスタンス化されます。
しかし、Protocolではこれが使えません。
ここにポケモンというものがあります。ポケモンは小さなモンスターです。
ポケモンの間にバトルを実装したいのですが
エラーが出ます
Swiftコンパイラに対して、実装がなにか分からないが絶対具象化されるということを伝える必要があります。それをどうコンパイラに伝えるか。
次のようにAnyPokemonを作ります
このラッパークラスを使えばこのようなコードが書けます。
しかし型情報を消してしまいました
型消去という名前が混乱のものです。これはソリューションではなく副作用です。
あとこういう宣言が出来ません。
Swiftはコードの共変性(より特殊な型をより一般的な型の代替にすること)に対応していません。
- 型とはなんぞやという話をしました
- 皆さんが独自に型を定義できる
- 型の定義は頭に浮かびますか?
- 具象と抽象がある
- 型消去の話をしました
QA
プロトコルがタイプと連携されている、扱いにくかったものでしたね。ほかに型消去の例はありますか?
プロトコル上のGenericタイプの例でしたがGenericTypeが必要ない時でもファンクションがreturnした時に必要ないことがあります。しかしSwiftコンパイラは推論しようとする。その制限を回避するために型消去を消す人もいる。
型というわけではないがExtensionのソリューションはありますか?
ない
Appleが型消去のスタンダードライブラリに何を使っていますか?
(AnyClass?)
ここまでの事例以外でプロジェクトやビジネス上の理由で問題を解決しようとしたんでしょうか
本番環境で型消去を、同僚が遭遇してEraseSwiftというライブラリを持っていて、FacebookのFluxパターンを追っています。一方行のデータフローがあってSubscriberがレシーブする、そこで型消去を使っていた。Subscriberが何でも受け取れるようにする、そういうところで型消去を使っていました。
リストの話をしていましたね。新しいSwiftで反変性と共変性について書かれている?
タイムラインはっきりしたことは分からない。型消去はかなり限定されたものになっていくと思いますが。
Ruby, Javascriptから来ました。私は型のない言語です。型嫌いです。どう学んだらいいですか?
(会場笑)
まずはSwiftを書いてください。
(会場笑)
もっとありますよ?コンパイラで何かをした時にいつも怒られます。そういうところでいろいろ試行錯誤になる。最終的には型安全なコードが書けるようになったんだ、と3ヶ月で自信が持てるのではないでしょうか。
Swiftプログラマですが私は型が好きです。型消去についてもう一度、一言でまとめるとを聞かせてほしい。
型消去の定義をもう一度まとめてということですね?トークをまとめるには非常に苦労しました。4つ定義がありました。話す度にそれじゃ違うよと言われ続けました。ベストな定義は、型消去はデザインパターンであるということですね。ラッパーで、イニシャライザに制約があるプロトコルの実装で具体化しようとしているプロトコルの時のみに使うということです。 もっと良い定義があったらぜひ聞きたいです。
このボイラープレートコードは、もっと長いものがあります。1行ずつ呼んでいかないとわからない、2週間ぐらいかかりました。なんでこんなことするんだと思いました。始めたことを後悔。最終的に、分かった、もっと協力なプログラマになれたと思うまでに苦労が必要だと思います。
型消去は、RealmとHimotokiをつなぎこむ汎用functionを作る時に使えそう、かな?Decodableのインスタンスの型をもとにRealm.Objectの型を決める時にprotocolのtypealias増やさなくてよさそう。#tryswiftconf
— toshi0383 (@toshi0383) March 2, 2016
まとめを更新しました。「Keep Calm and Type Erase On -型消去とはどういうことなのか- #tryswiftconf」 https://t.co/UGcw2tJlkr
— トゥギャッター開発まとめ (@tg__dev) March 2, 2016
気に入った記事は はてなブックマーク
はてなブックマークアプリiOS開発チームから来ました! はてなブックマークにはSwift特集があります! 良い記事を見逃さないように、ご利用ください! http://b.hatena.ne.jp/hotentry/it/Swift
そして良いまとめ記事があったらはてなブックマークでブックマークしましょう! try! Swift の記事で盛り上がると嬉しいです!