1. taketo1024

    No comment

    taketo1024
Changes in body
Source | HTML | Preview

社内の「Scala 勉強会」で Phantom Type (幽霊型)という厨二心をくすぐる感じのデザインパターンを教えてもらったので、Swiftという厨二心をくすぐる感じのデザインパターンを教えてもらったので、同じことを でもやってみました。インスタンスの状態チェックを実行時ではなくSwift でもやってみました。インスタンスの状態を変数ではなく型パラメータ として持つことで、状態チェックを実行時ではなく コンパイル時 に行えるという優れものです。

class Status{}
class NotReady: Status{}
class Ready: Status{}

class Something<T: Status> {
    static func createInstance() -> Something<NotReady> {
        return Something<NotReady>()
    }

    func readify() -> Something<Ready> {
        return Something<Ready>()
    }
}

extension Something where Status: Ready {
    func shout() {
        print("phantom types are awesome!")
    }
}

StatusNotReady, Ready をサブクラスに持つだけの空クラス(これが幽霊型)で、SomethingStatus 型の型パラメータ T を持っています。Something には where Status: Ready という 型パラメータ制約付きの拡張 によって、shout() という関数を追加しています。

createInstance()Something<NotReady> インスタンスが作られ、readify() を呼ぶと新たに Something<Ready> インスタンスが作られます。そうして作られた TReady のインスタンスに対してのみ shout() を呼ぶコードが書けるのです。

やってみましょう:

let s = Something.createInstance()
s.shout() // error: 'NotReady' is not a subtype of 'Ready'

ちゃんと コンパイルエラー が出ました!
一方で readify() を呼ぶと…

let s = Something.createInstance()
s.readify().shout() // phantom types are awesome!

エラーもなく、ちゃんと実行もできました!
Phantom Type カッコイイですね :trollface::thumbsup: