連載

改訂版
プロフェッショナルVB.NETプログラミング

Chapter 11 デリゲート

株式会社ピーデー 川俣 晶
2004/07/22
Page1 Page2 Page3 Page4


 本記事は、(株)技術評論社が発行する書籍『VB6プログラマーのための入門 Visual Basic .NET 独習講座』の一部分を許可を得て転載したものです。同書籍に関する詳しい情報については、本記事の最後に掲載しています。

共有メソッドへの委譲

 上記の例を見て、掛け算も足し算も完全に独立した処理であるため、共有メソッド(インスタンスを作成せずに呼び出せるメソッドを参照)にしても何ら問題ないことに気付いた人もいるだろう。では、共有メソッドへの委譲は記述できるのだろうか?

 リスト11-6は、そのように修正してみたプログラムである。

 1: Delegate Function SampleDelegate(ByVal x As Integer, ByVal y As Integer) As Integer
 2:
 3: Public Class SampleClass
 4:   Public Shared Function MethodMult(ByVal x As Integer, ByVal y As Integer) As Integer
 5:     Return x * y
 6:   End Function
 7:
 8:   Public Shared Function MethodPlus(ByVal x As Integer, ByVal y As Integer) As Integer
 9:     Return x + y
10:   End Function
11: End Class
12:
13: Public Class Form1
14:   Inherits System.Windows.Forms.Form
15:
16: …Windows フォーム デザイナで生成されたコード…
17:
18:   Private Sub calc(ByVal x As Integer, ByVal y As Integer, ByVal calcMethod As SampleDelegate)
19:     Dim result As Integer = calcMethod(x, y)
20:     Trace.WriteLine(result)
21:   End Sub
22:
23:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
24:     Dim instance As New SampleClass()
25:     calc(2, 3, AddressOf SampleClass.MethodMult)
26:     calc(2, 3, AddressOf SampleClass.MethodPlus)
27:   End Sub
28: End Class
リスト11-6 リスト11-1の委譲先となる2つのメソッドを共有メソッドにしたプログラム

 これを実行すると以下のようになる。

1: 6
2: 5
リスト11-7 リスト11-6の実行結果

 共有メソッドを指定するために、インスタンス名の代わりにクラス名を使用することができる。25行目のSampleClass.MethodMultのようにメソッド名を記述すれば、その共有メソッドが利用可能である。それ以外には特別な記述はなく、デリゲートの宣言や呼び出し時に特別な配慮は必要ないことが分かると思う。

デリゲートはインスタンスを選ぶ

 これは非常に重要なことなので、よく頭に刻み込んでほしいところなのだが、共有メソッドを使う場合を除き、デリゲートはインスタンスとメソッドの情報を扱うつまり、デリゲートが委譲する先は、ただ単に指定されたメソッドが呼ばれるだけでなく、呼び出し時にどのインスタンスかも明示されるリスト11-8は、複数インスタンスのメソッドを委譲先として使用したサンプル・プログラムである。

 1: Delegate Function SampleDelegate(ByVal x As Integer, ByVal y As Integer) As Integer
 2:
 3: Public Class SampleClass
 4:   Public result As Integer
 5:   Public Function SampleMethod(ByVal x As Integer, ByVal y As Integer) As Integer
 6:     result = x * y
 7:   End Function
 8: End Class
 9:
10: Public Class Form1
11:   Inherits System.Windows.Forms.Form
12:
13: …Windows フォーム デザイナで生成されたコード…
14:
15:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
16:     Dim instance1 As New SampleClass()
17:     Dim instance2 As New SampleClass()
18:     Dim d1 As SampleDelegate = AddressOf instance1.SampleMethod
19:     Dim d2 As SampleDelegate = AddressOf instance2.SampleMethod
20:     d1(2, 3)
21:     d2(4, 5)
22:     Trace.WriteLine(instance1.result)
23:     Trace.WriteLine(instance2.result)
24:   End Sub
25: End Class
リスト11-8 2つの異なるインスタンスのデリゲートを呼び出すプログラム

 これを実行すると以下のようになる。

1: 6
2: 20
リスト11-9 リスト11-8の実行結果

 ここでは、同じSampleClassクラスのインスタンスを2つ作成している(16〜17行目)。この2つのインスタンスに対して、別々にデリゲート・インスタンスを作成している(18〜19行目)。

 さて、ここからがこのサンプル・プログラム最大の注目点だ。20〜21行目のメソッド呼び出しには、どのSampleClassインスタンスを対象にするか、明示的には表現されていない。しかし、デリゲート・インスタンスは、どのSampleClassインスタンスを対象とするかを覚えているので、間違いなく、18〜19行目で指定されたSampleClassインスタンスのメソッドを呼び出す。

 このように、デリゲートはメソッドだけでなく、インスタンスも識別することをよく覚えておいていただきたい。特に、C/C++の関数ポインタをご存じの方は注意が必要である。関数ポインタは関数を特定する機能しか持たず、インスタンスを特定する情報は持たないのである。

戻り値と引数が合えば委譲できる

 デリゲートは、対象となるメソッドにPrivateキーワードなどが付加されてアクセス権が与えられていない場合などを除き、戻り値と引数が合えば委譲できる。別クラスの異なる名前のメソッドであっても、戻り値と引数だけ合っていれば委譲できる。リスト11-9は、まったく無関係な別クラスの異なる名前のメソッドに委譲した例である。

 1: Delegate Function SampleDelegate(ByVal x As Integer, ByVal y As Integer) As Integer
 2:
 3: Public Class SampleClass1
 4:   Public result As Integer
 5:   Public Function MethodMult(ByVal x As Integer, ByVal y As Integer) As Integer
 6:     result = x * y
 7:   End Function
 8: End Class
 9:
10: Public Class SampleClass2
11:   Public result As Integer
12:   Public Function MethodPlus(ByVal x As Integer, ByVal y As Integer) As Integer
13:     result = x + y
14:   End Function
15: End Class
16:
17: Public Class Form1
18:   Inherits System.Windows.Forms.Form
19:
20: …Windows フォーム デザイナで生成されたコード…
21:
22:   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
23:     Dim instance1 As New SampleClass1()
24:     Dim instance2 As New SampleClass2()
25:     Dim d1 As SampleDelegate = AddressOf instance1.MethodMult
26:     Dim d2 As SampleDelegate = AddressOf instance2.MethodPlus
27:     d1(2, 3)
28:     d2(4, 5)
29:     Trace.WriteLine(instance1.result)
30:     Trace.WriteLine(instance2.result)
31:   End Sub
32: End Class
リスト11-9 無関係なクラスの異なる名前のメソッドに委譲するプログラム

 これを実行すると以下のようになる。

1: 6
2: 9
リスト11-10 リスト11-9の実行結果

 このように、デリゲートの対象となるメソッドは、クラスの種類やメソッド名などには制限されない。


 INDEX
  [連載] 改訂版 プロフェッショナルVB.NETプログラミング
  Chapter 11 デリゲート
    1.デリゲートとは何か/2つの異なるメソッドに委譲する
  2.共有メソッドへの委譲/デリゲートはインスタンスを選ぶ/戻り値と引数が合えば委譲できる
    3.継承でも実現できるか?/デリゲートをオブジェクトとして使う/Privateキーワードの付いたメソッドへの委譲
    4.委譲先を複数持たせる/委譲先リストの変更/デリゲート型の同一性
 
「改訂版 プロフェッショナルVB.NETプログラミング 」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH