SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

C#プログラマのためのF#入門

F#のクラスの拡張

C#プログラマのためのF#入門(5)

  • X ポスト
  • このエントリーをはてなブックマークに追加

プロパティの拡張

 次にプロパティの拡張について解説します。プロパティを追加してクラスを拡張するのもメソッド同様いたってシンプルです。

 type クラス名withで拡張するクラスを指定し、member以降にプロパティ名と値を定義します。

[構文]プロパティの拡張
type 拡張するクラス名 with
   member セルフ識別子.プロパティ名
     with get() = get関数ボディ
     and set(パラメータ) = セット関数ボディ

 以下はプロパティによるクラス拡張の例です。

[リスト3]プロパティによるクラス拡張
open System

type System.Random with  //拡張されるクラス名
  member this.testProp  //プロパティ名
    with get() = this.Next(0, 5)  //※1 getプロパティの設定
  
let a = new Random();; //Randomクラスのインスタンス作成
printf "%d" (a.testProp);;  //※2

 ▼

type Random with
  member testProp : int
val a : Random

>
4val it : unit = ()

 リスト3では、既存のSystem.Randomクラスに、Nextメソッドによる0-5までのランダムな値を取得し(※1)それをgetプロパティ"testProp"として定義しています。

 最後に追加されたプロパティを、"printf"で表示(※2)させています。セルフ識別子の部分には通常のメンバーの時同様にローカルでの識別子を指定します。

 このプロパティによるクラス拡張機能を使用すれば、例えば、WPFやSilverlightなどの添付プロパティの定義を拡張プロパティとしてクラスの外にまとめ、コントロールにプロパティは定義しながらも拡張プロパティのインポートの有無によってのみ切り替えることなどが可能になります(添付プロパティとは、親オブジェクトで定義されたプロパティに子オブジェクトで別の値を定義するなどして使用できるグローバルなプロパティのことです)。

イベント

 メソッド、プロパティだけではなくF#のクラス拡張ではイベントも定義することができますが、クラス拡張の前に、F#のイベントについて基本がまだでしたので、先に説明します。

(1)既存のイベントに動作を追加

 既存のイベントに動作を追加するには以下のように行います。

[構文]既存のイベントに動作を追加
既存のイベント.Add(イベントハンドラ)

 以下の例では、form.Clickイベントにクリックされたらフォームを閉じるというハンドラを追加しています。

[リスト4]既存イベントform.Clickにハンドラを追加
open System.Windows.Forms

let form = new Form(Text="F# Windows Form for Event Test",
                    Visible = true,
                    TopMost = true)

form.Click.Add(fun _ -> form.Close())  //イベントハンドラの追加
Application.Run(form)

 Addメソッドに渡すイベントハンドラメソッドはパラメータを1つ受け取り、unitを返します。下記の例ではイベントハンドラの部分をラムダ式で表していますが、ラムダ式の代わりに関数名を使用することも可能です。

(2)イベントの新規作成

 以下はC#によるイベント新規作成の例です。

[リスト5]パラメータを受け取るイベント: C#
      public class testEventArgs : EventArgs//※4 EventArgsを継承したパラメター用のクラス作成
    {
      public string triggerParam;
    }
    public delegate void testEvHand(object x, testEventArgs y);  //デリゲートの宣言
   class Class
   {
     public event testEvHand testEvent; //※1 イベント本体(testEvent)の定義
     public void testHandler( object x, testEventArgs y ) //※2 イベントハンドラの定義
     {
         Console.WriteLine(y.triggerParam);
     }
     static void Main(string[] args)
     {
       Class testObj1 = new Class();
       testObj1.testEvent += new testEvHand(testObj1.testHandler); //イベントハンドラの追加
       testEventArgs testObj2 = new testEventArgs(); //パラメータ用クラスのインスタンス
       testObj2.triggerParam = "Event : Triggerd"; //※3 パラメータとして渡したい情報を記録
       testObj1.testEvent( testObj1, testObj2 );// ※5 イベントを呼び出しパラメータを渡す。
     }
   }

 上の例では、イベントtestEvent(※1)とそのイベントハンドラtestEvHandの定義(※2)し、さらにそのイベントに引数を渡すようにしています。

 イベントに引数を渡すために、Sytem.EventArgsクラスを継承したパラメータを記録(※3)するためのクラスを作成(※4)し、そのクラスのインスタンス経由でパラメータを渡し(※5)ています。

 次に同様に新規イベント作成の処理をF#で行ってみましょう。まず、構文から説明します。

[構文]新規イベント作成
typeクラス名() =
    let組名 = new Event<_>()
//イベントハンドラの追加
    member セルフ識別子.イベント名 =
       Event.add (イベントハンドラ) 組名.Publish
       Event.add (イベントハンドラ) 組名.Publish
        …
//トリガー定義
    member セルフ識別子.トリガー名(パラメータ) =
       組名.Trigger(パラメータ)

//イベント呼び出し
letインスタンス名 = クラス名()
インスタンス名.イベント名
インスタンス名.トリガー名(パラメータ)

 Event関数は2つの要素から構成される組(タプル)を作成します。1つ目の要素は、トリガー(イベントを発生させる物)用のフィールドで、2つ目の要素にはイベントデータ用の値が入ります。

 その後に、イベントハンドラとトリガーを定義します。トリガーには1つ引数を与えることができます。イベントは、イベント用に作成したクラスのインスタンス経由でイベントを呼び出し、その後、トリガーに引数を渡します。

 では、先ほどC#イベントを新規作成したようにF#でもイベントを作成してみましょう。

[リスト6]パラメータを受け取るイベント: F#
type testClass() =
    let testTuple = new Event<_>() //※1 testTuple組は二つのフィールドからなる
    member this.testEvent() =  //※2 イベントハンドラ追加し、イベントを発行
        Event.add(fun str -> printfn "%s" str) testTuple.Publish
    member this.testTrigger(a) =//※3トリガー定義
        testTuple.Trigger(a)

//※4 イベントの呼び出し
let testObj = testClass()
testObj.testEvent()
testObj.testTrigger("Event : Triggered") //※5 パラメータを渡す

 ▼

Event : Triggered

type testClass =
  class
    new : unit -> testClass
    member testEvent : unit -> unit
    member testTrigger : a:string -> unit
  end
val testObj : testClass

 F#では、直接パラメータを渡すことが可能で、新たなクラスを作成する必要がありません。

 まず、トリガー用とイベント用のフィールドを持つ組testTupleをnew Eventで作成します(※1)。memberキーワードとEvent.addメソッドでイベントハンドラを追加(※2)して、その後トリガーを定義(※3)します。例で設定してあるイベントハンドラは引数としてイベントに渡された値を表示するというものです。イベントの呼び出(※4)しは、イベント用クラスtestClassのインスタンス経由でイベント(testEvent)とトリガー(testTrigger)を呼び、そのときにパラメータを渡します(※5)。

次のページ
まとめ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
C#プログラマのためのF#入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 星山 仁美(ホシヤマ ヒトミ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/4990 2010/04/01 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング