スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門初級編 第13回 Delegates と Events(1)

まずはデリゲートを紹介します。
 
デリゲートは、「関数+アルファ」というような感じで「関数をクラスのインスタンスとして扱い、関数値にはない機能が付け加わっているもの」と大雑把にとりあえず理解しておいていただければと思います。
 
まずdelegateを使うには定義が必要となります。
type MyDelegateTypeiitoi = delegate of int * int -> int      
というように定義します。これで、MyDelegeteTypeiitoiという名前のクラスが定義されます。(これはSystem.Delegateの子クラス(サブクラス)となります。)
次に、インスタンスをつくってみます。
let delegMySum = 
    new MyDelegateTypeiitoi(fun x y -> x + y)
 
暗黙的に作られるコンストラクタの引数としてint -> int -> int 型の関数を渡していることに留意してください。(int*int -> int 型ではありません。)
値に適用するにはInvokeメソッドを使います。
 
> delegMySum.Invoke (1,5);;
val it : int = 6
 
それでは、次に普通の関数値にはない機能を紹介します。
自分で定義したデリゲートはSystem.Delegateの派生クラスなので、そのインスタンスは親元のメソッドを継承しています。(上のInvokeメソッドもそのうちの一つです。)
Combineメソッドもそのうちの一つで、二つのdelegateを合わせることができます。
例です。
 
type MyDelegeteTypeiitou = delegate of int * int -> unit  
 
let delegMySum = 
    new MyDelegeteTypeiitou(fun x y  -> printfn "sum is %d" (x + y) )
    
let delegMyMul = 
    new MyDelegeteTypeiitou(fun x y  -> printfn "mul is%d" (x * y) )
                                
let combinedDelg = MyDelegeteTypeiitou.Combine (delegMySum,delegMyMul)
 
ここでcombinedDelgの型を調べてみると
val combinedDelg : System.Delegateとなっています。。
 
ただMyDelegeteTypeiitou型のインスタンスとして使うにはキャストが必要となります。
 
> let ApplyBoth = combinedDelg :?> MyDelegeteTypeiitou;;
val ApplyBoth : MyDelegeteTypeiitou
 
> ApplyBoth.Invoke (3,4);;
sum is 7
mul is12
val it : unit = ()
 
次はイベントの紹介です。ちょっと回り道をします。(一昨日の内容とだぶってます。)
例えばウィンドウズのフォームのプログラミングでは、「ボタンが押されたら何らかの処理をする。」というように、何か起こったときに、「これこれをする」という処理をプログラムしていくのが必須のテクニックになります。フォーム側のコードを変更せずにこれを可能にするには、外側からのリクエストを受け付けて記録しておくメカニズムと、何か起こったときに、リクエストに答えるメカニズムの実装しておくことが必要となります。、
 
次のクラス定義を見てください。
 
type PublisherExamp () =
    let mutable _memoOfWhatToDo : list<PublisherExamp -> unit> = []
    member this.RememberWhatToDo (func) =
        _memoOfWhatToDo <- (func :: _memoOfWhatToDo) //連結して、上書き
    member private this.publishSomething () =
        for f in _memoOfWhatToDo do
            f this
    member this.SomethingHappen () =
        this.publishSomething ()            
        
まず定義部分一行目の
    let mutable _memoOfWhatToDo : list<PublisherExamp -> unit> = []
は、何か起こったときにすることを、保存しておくところです。
実際には、(PublisherExamp -> unit)型の関数を保存しておき、何かあった時には、自分自身のインスタンスを引数にして、リスト内のすべての関数を実行するようにします。
 
2,3行目の
    member this.RememberWhatToDo (func) =
        _memoOfWhatToDo <- (func :: _memoOfWhatToDo)
は、外部からの、リクエスト(何か起こったときにすること)を、上の_memoOfWhatToDoに付け足すためのメソッドです。
 
4,5,6行目の
    member private this.publishSomething () =
        for f in _memoOfWhatToDo do
            f this
は「何かあった時」に、自分自身のインスタンスを引数にして、リスト内のすべての関数を実行するメソッドです。
 
7,8行目の
    member this.SomethingHappen () =
        this.publishSomething ()
は、「何かあった」というのを、人為的に作り出すための、便宜上のメソッドです。
 
さて使ってみます。
まずインスタンスを作成します。
> let t = new PublisherExamp();;
val t : PublisherExamp
 
「何かあった時(トリガーが引かれたとき、イベントが点火したとき」)にすることを登録します。
> t.RememberWhatToDo (fun (x:PublisherExamp) -> printfn "What to do is done 1 ");;
val it : unit = ()
 
もう一個「何かあった時(トリガーが引かれたとき、イベントが点火したとき」)にすることを登録します。
> t.RememberWhatToDo (fun (x:PublisherExamp) -> printfn "What to do is done 2 ");;
val it : unit = ()
 
人為的にトリガーを引きます。
> t.SomethingHappen();;
What to do is done 2 
What to do is done 1 
val it : unit = ()
 
なお簡易のため、登録する関数はfun (x:PublisherExamp) -> printfn "What to do is done 1 ")というように、引数xを実際には使っていませんが、xのプロパティ、メソッドを、関数内で利用できることに注意しておいてください。
 
さて、基本事項の紹介が終わったところで、実際にはこのような仕組みを、どのように実装していくかがスタンダードであるかを紹介してきます。
まず、上の例では関数を登録してそれを実行していましたが、一般的に.NETではdelegateを使用します。
 
(続く)
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。