1. taketo1024

    Posted

    taketo1024
Changes in title
+Swift で Phantom Type (幽霊型)
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,45 @@
+社内の「Scala 勉強会」で **Phantom Type (幽霊型)** という厨二心をくすぐる感じのデザインパターンを教えてもらったので、Swift でもやってみました。インスタンスの状態チェックを実行時ではなく **コンパイル時** に行えるという優れものです。
+
+```
+class Status{}
+class NotReady: Status{}
+class Ready: Status{}
+
+class Something<T: Status> {
+ static func createInstance() -> Something<N> {
+ return Something<NotReady>()
+ }
+
+ func readify() -> Something<Ready> {
+ return Something<Ready>()
+ }
+}
+
+extension Something where Status: Ready {
+ func shout() {
+ print("phantom types are awesome!")
+ }
+}
+```
+
+`Status` は `NotReady`, `Ready` をサブクラスに持つだけの空クラス(これが幽霊型)で、`Something` は `Status` 型の型パラメータ `T` を持っています。`Something` には `where Status: Ready` という **型パラメータ制約付きの拡張** によって、`shout()` という関数を追加しています。
+
+`createInstance()` で`Something<NotReady>` インスタンスが作られ、`readify()` を呼ぶと新たに `Something<Ready>` インスタンスが作られます。そうして作られた `T` が `Ready` のインスタンスに対してのみ `shout()` を呼ぶコードが書けるのです。
+
+やってみましょう:
+
+```
+let s = Something.createInstance()
+s.shout() // error: 'N' is not a subtype of 'Y'
+```
+
+ちゃんと **コンパイルエラー** が出ました!
+一方で `readify()` を呼ぶと…
+
+```
+let s = Something.createInstance().readify()
+s.shout() // phantom types are awesome!
+```
+
+エラーもなく、ちゃんと実行もできました!
+**Phantom Type** カッコイイですね :trollface::+1: