インタフェース

インタフェースを使うことで 「このメソッドは必ず実装するように」というような 制約をクラスに持たせることが出来ます。 インタフェースは、抽象メソッドとプロパティのみを持つことができ、 デフォルトの実装は提供しません。 また直接インスタンス化することも出来ません。 クラスに実装するか、 後述するObject Expressionを通して利用していくことになります。 インタフェースの構文は次の通りです
インタフェース
type インタフェース名 = interface 継承宣言 メンバ定義 end
interfaceとendは軽量構文時は省略出来ます。 抽象メソッドの回の説明で作成した抽象メソッドを インタフェースにしたのが次です。
インタフェースの例
type IAnimal = interface
    abstract member Bark : unit -> unit
    end;;
インタフェースの例(軽量構文)
type IAnimal =
    abstract member Bark : unit -> unit
これを用いて前回のプログラムを書き直すと 次のようになります。
インタフェースの利用例
type IAnimal = interface
    abstract member Bark : unit -> unit
    end;;
type Dog() = class
    interface IAnimal with
        member this.Bark () = printfn "わんわん"
        end
    end;;
type Cat() = class
    interface IAnimal with
        member this.Bark () = printfn "ニャー"
        end
    end;;
let d = new Dog();;
// d.Bark();; //これはエラー
(d :> IAnimal).Bark();;
let c = new Cat();;
(c :> IAnimal).Bark();;
インタフェースの利用例
type IAnimal =
    abstract member Bark : unit -> unit
type Dog() =
    interface IAnimal with
        member this.Bark () = printfn "わんわん"
type Cat() =
    interface IAnimal with
        member this.Bark () = printfn "ニャー"
let d = new Dog()
// d.Bark() //これはエラー
(d :> IAnimal).Bark()
let c = new Cat()
(c :> IAnimal).Bark()
インタフェースの実装の構文は次の通りです。
インタフェースの実装
interface インタフェース名 with 値またはメンバの定義 end
ちょっとイケてないと思うのは コメントアウトしている箇所のように記述できない点です。 これをキャストなしで済ますには、 次のようにする必要があります。
インタフェースの利用例2
type IAnimal = interface
    abstract member Bark : unit -> unit
    end;;
type Dog() = class
    interface IAnimal with
        member this.Bark () = printfn "わんわん"
        end
    member this.Bark () = (this :> IAnimal).Bark()
    end;;
type Cat() = class
    interface IAnimal with
        member this.Bark () = printfn "ニャー"
        end
    member this.Bark () = (this :> IAnimal).Bark()
    end;;
let d = new Dog();;
d.Bark();;
let c = new Cat();;
c.Bark();;
インタフェースの利用例2(軽量構文)
type IAnimal =
    abstract member Bark : unit -> unit
type Dog() =
    interface IAnimal with
        member this.Bark () = printfn "わんわん"
    member this.Bark () = (this :> IAnimal).Bark()
type Cat() =
    interface IAnimal with
        member this.Bark () = printfn "ニャー"
    member this.Bark () = (this :> IAnimal).Bark()
let d = new Dog()
d.Bark()
let c = new Cat()
c.Bark()
二度手間になってしまいますがクラスのBarkの実装を インターフェースの実装に委譲しています。

インタフェースの継承

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