インタフェース

インタフェースを使うことで 「このメソッドは必ず実装するように」というような 制約をクラスに持たせることが出来ます。 インタフェースは、抽象メソッドとプロパティのみを持つことができ、 デフォルトの実装は提供しません。 また直接インスタンス化することも出来ません。 クラスに実装するか、 後述するObject Expressionを通して利用していくことになります。 インタフェースの構文は次の通りです
インタフェース
type インタフェース名 = interface 継承宣言 メンバ定義 end
interfaceとendは#lightシンタックス時は省略出来ます。 抽象メソッドの回の説明で作成した抽象メソッドを インタフェースにしたのが次です。
インタフェースの例
type AnimalInterface = interface
    abstract Bark : unit -> unit
    end;;
これを用いて前回のプログラムを書き直すと 次のようになります。
インタフェースの利用例
type Dog = class
    new () = {}
    interface AnimalInterface with
        member x.Bark () = System.Console.WriteLine("wan wan")
    end
end;;
type Cat = class
    new () = {}
    interface AnimalInterface with
        member x.Bark () = System.Console.WriteLine("nya- nya-")
    end
end;;

//let a = new Dog() in a.Bark();;
let a = new Dog() in (a :> AnimalInterface).Bark();;
let b = new Cat() in (b :> AnimalInterface).Bark();;
インタフェースの実装の構文は次の通りです。
インタフェースの実装
interface インタフェース名 with 値またはメンバの定義 end
ちょっとイケてないと思うのは コメントアウトしている箇所のように記述できない点です。 これをキャストなしで済ますには、 次のようにする必要があります。
インタフェースの利用例2
type AnimalInterface = interface
    abstract Bark : unit -> unit
    end;;
type Dog = class
    new () = {}
    interface AnimalInterface with
        member x.Bark () = System.Console.WriteLine("wan wan")
    end
    member x.Bark () = System.Console.WriteLine("wan wan")
end;;
type Cat = class
    new () = {}
    interface AnimalInterface with
        member x.Bark () = System.Console.WriteLine("nya- nya-")
    end
    member x.Bark () = System.Console.WriteLine("nya- nya-")
end;;

let a = new Dog() in a.Bark();;
let b = new Cat() in b.Bark();;
しかし、これでは同じ内容の関数が2箇所に書かれてしまうため インタフェースの意味がないように思います。 また、インタフェースとクラスの実装を別々にすることも出来てしまい その場合、クラスにかいてあるほうの実装が優先されるようです。 このあたりのことはFoundations of F#の98ページあたりに書いてありますが これは将来のバージョンで改善してほしいなと思います。

インタフェースの継承

インタフェースはインタフェースを継承することも出来ます。 継承にはinheritキーワードを用います。
インタフェースの継承
type IA = interface abstract One : int -> int end;;
type IB = interface abstract Two : int -> int end;;
type IC = interface
    inherit IA
    inherit IB
    abstract Three : int -> int
end;;
インタフェースは複数継承することができます。 ICはIAとIBを継承しているため One,Two,Three3つの抽象メソッドを持ちます。 そして、これを定数関数として実装したのが次の例です。
継承したインタフェースの利用
type ClassWithIC = class
    new () = {}
    interface IC with
        member x.One n = 1
        member x.Two n = 2
        member x.Three n = 3
    end
end;;
このように、継承して作成したインタフェースも 通常のインタフェースと同様に利用することができます。