(3)イベントの拡張
メソッド、プロパティ同様にイベントによるクラス拡張も以下の構文を用いて行うことが可能です。
let 組名 = new Event<_>() type 拡張クラス名 with member イベント定義
リスト7はSystem.Stringにイベントを追加し拡張する例です。
open System.Windows.Forms let event = new Event<_>() //※1 type System.String with //※2 System.Stringの拡張 member this.testEvent() = Event.add(fun str -> printfn "%s" str) event.Publish //※3 member this.testTrigger(a) = //※4 トリガー定義 event.Trigger(a) //※5 イベント呼び出し let testIns = System.String(null) testIns.testEvent() testIns.testTrigger("aaaa")
▼
aaaa val event : Event<string> type String with member testEvent : unit -> unit type String with member testTrigger : a:string -> unit val testIns : System.String = ""
まず、new Eventで組を作成(※1)し、続いて拡張するクラスを指定(※2)します。
イベントハンドラとして、渡された引数を表示するラムダ式を追加しイベントを発行(※3)します。通常のイベントの新規作成と同様に、イベントトリガーもmemberとして定義(※4)します。
イベントがSystem.Stringクラスに追加され、String型のインスタンス経由でイベントを呼ぶ(※5)ことができるようになります。
ある種の機能が不可なものよりは可のほうが柔軟な言語とは言えるかもしれませんが、残念ながら正直、どういったシチュエーションでイベント拡張を利用すると効果的なのか作者には使いどころが思い当たりません。
(4)デリゲート(委譲)
関数が第一級(ファーストクラス)オブジェクトのF#においては関数をパラメータなどの値として表すことが可能ですが、その他の.NETフレームワークのAPIと相互運用する場合には、デリゲートを使用します。
delegate int testDel(int x, int y); //デリゲート宣言 class testClass { public int testMethod(int x, int y) //※1 { return x * y; } } class Class1 { [STAThread] static void Main(string[] args) { testClass instance = new testClass(); testDel testIns = new testDel(instance.testMethod); // testMethodを委譲 Console.WriteLine(testIns(5, 10)); //(※2)デリゲート型のインスタンス経由で呼び出し } }
引数を2つ受け取るtestMethod(※1)を呼び出すために、デリゲート型testDelのインスタンス経由でパラメータを渡し(※2)、メソッドtestMethodを呼び出しています。
F#のデリゲートの使用方法はC#のそれと大変似ています。
type デリゲート名 = delegate of引数の型 -> 戻り値の型
上記のC#の例はF#では以下のようになります。
type testdel = delegate of (int*int) -> int //デリゲート宣言 let a = new testdel(fun (x, y) -> x * y) //※1 ラムダ式を委譲 Console.WriteLine(a.Invoke(5, 10));; // ※2 Invokeメソッド経由で呼び出し
▼
50 type testdel = delegate of (int * int) -> int val a : testdel
ラムダ式を用いると若干すっきりしますね。
デリゲートの宣言はC#と非常に似ていますが、delegateに委譲したラムダ式(※1)を呼ぶ際には、Invokeメソッドを使用(※2)します。
残念ながら、現時点では拡張されたプロパティやイベントにはF#プログラムからのみアクセスできるようです。
まとめ
今回はクラスの拡張機能について解説しました。新たな継承クラスを作成したり、クラスへの変更なしに様々なオブジェクトが拡張できる機能を使ってより効率的なコーディングをしてください。次回はF#のオブジェクト指向の最終回としてオブジェクト式について解説したいと思います。