連載
プロフェッショナルVB.NETプログラミング
第23回 処理を委譲するデリゲート
(株)ピーデー
川俣 晶
2002/11/02
|
|
共有メソッドへの委譲
上記の例を見て、掛け算も足し算も完全に独立した処理であり、共有メソッド(Sharedなメソッド)にしても何ら問題ないことに気付いた人もいるだろう。では、共有メソッドへの委譲は記述できるのだろうか? 以下はそのように修正してみたものである。
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
|
|
サンプル・プログラム1の委譲先となる2つのメソッドを共有メソッドにしたサンプル・プログラム4 |
これを実行すると以下のようになる。
Sharedなメソッドを指定するために、インスタンス名の代わりにクラス名を使用することができる。25行目のSampleClass.MethodMultのようにメソッド名を記述すれば、そのままSharedなメソッドを利用可能である。それ以外には特別な記述はなく、デリゲートの宣言や呼び出し時に特別な配慮は必要ないことが分かると思う。
デリゲートはインスタンスを選ぶ
これは非常に重要なことなので、よく頭に刻み込んでほしいところなのだが、共有メソッドを使う場合を除き、デリゲートはインスタンスとメソッドの情報を扱う。つまり、デリゲートが委譲する先は、ただ単に指定されたメソッドが呼ばれるだけでなく、呼び出し時にどのインスタンスかも明示される。以下は、複数インスタンスのメソッドを委譲先として使用したサンプル・プログラムである。
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
|
|
2つの異なるインスタンスのデリゲートを呼び出すサンプル・プログラム5 |
これを実行すると以下のようになる。
ここでは、同じSampleClassクラスのインスタンスを2つ作成している(16〜17行目)。この2つのインスタンスに対して別々にデリゲート・インスタンスを作成している(18〜19行目)。さてここからが、このサンプル・プログラム最大の注目点なのだが、20〜21行目のメソッド呼び出しには、どのSampleClassインスタンスを対象にするか、明示的には表現されていない。しかし、デリゲート・インスタンスは、どのSampleClassインスタンスを対象とするかを覚えているので、間違いなく、18〜19行目で指定されたSampleClassインスタンスのメソッドを呼び出す。
このように、デリゲートはメソッドだけでなくインスタンスも識別することを、よく覚えておいていただきたい。特にC/C++の関数ポインタをご存じの方は注意が必要である。関数ポインタは関数を特定する機能しか持たず、インスタンスを特定する情報は持たないのである。
戻り値と引数が合えば委譲できる
デリゲートは、対象となるメソッドにPrivateキーワードなどが付加されてアクセス権が与えられていない場合などを除き、戻り値と引数が合えば委譲できる。別クラスの異なる名前のメソッドであっても、戻り値と引数だけ合っていれば委譲できる。以下は、まったく無関係な別クラスの異なる名前のメソッドに委譲した例である。
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
|
|
無関係なクラスの異なる名前のメソッドに委譲するサンプル・プログラム6 |
これを実行すると以下のようになる。
このサンプル・プログラムはここまで説明した知識だけで読みとれると思う。このように、デリゲートは自由度の高い機能なのである。
Insider.NET 記事ランキング
本日
月間