![]() |
![]() |
delegate-id MessageHandler (str as string).
end delegate.
class-id DelegatesEvents.
01 MessageArrived event type MessageHandler static.
method-id Main static.
*> explicit delegate construction
invoke new MessageHandler(MyHandler)
*> implicit delegate construction
declare handler as type MessageHandler = method MyHandler
*> subscribe to an event
attach method MyHandler to MessageArrived
*> raise the event
invoke MessageArrived("Test message")
*> unsubscribe from the event
detach method MyHandler from MessageArrived
*> Throws a null reference exception as there are no subscribers
invoke MessageArrived("Test message 2")
*> Safely raising an #event
declare handler2 as type MessageHandler = MessageArrived
if handler2 not equals null
invoke handler1("Safe message")
end-if
end method.
method-id MyHandler static (str as string).
display str
end method.
end class.
デリゲートはメソッドへの参照を保持するクラスであり、インスタンス メソッドの場合は、そのメソッドを呼び出せるオブジェクトとなります。
デリゲート クラスのインスタンスが作成されると、保存されたインスタンス上の参照先メソッドが呼び出される場所で呼び出せるようになります。
1 つのデリゲート型に保持できるのは特定のシグネチャのメソッドへの参照のみであるため、デリゲートの作成および呼び出しにおいて型の安全性が保たれます。
COBOL でデリゲートを定義する際には、DELEGATE-ID キーワードと、シグネチャを指定する手続き部の見出しを使用します。たとえば、文字列パラメーターを持ち、binary-long を返すデリゲートは、次のように宣言します。
delegate-id MyDelegate. procedure division using by value s1 as string returning n1 as binary-long. end delegate.
A method group is a method invocation expression preceded by the keyword METHOD, and without any parameters. When a method group is specified, it denotes one of the set of methods with the specified name in the specified class.
An implicit conversion exists between a method group and a specific delegate type, if one of the methods identified by the method group has a signature which is compatible with that delegate type.
For example, to create an instance of the delegate MyDelegate you declared above, that points to a suitable method:
01 d type MyDelegate. 01 c type Class1. ... set d to method c::m class-id Class1. method-id m. procedure division using by value s1 as string returning n1 as binary-long. end method. method-id m. procedure division using by value s1 as string s2 as string returning n1 as binary-long. end method. end class.
In the example above, the SET statement automatically selects the first overload of the method m as it has a signature which is compatible with that of the delegate type MyDelegate.
A method group can also be used as a parameter to a method, when that method has an argument of a compatible delegate type. Again, an implicit conversion from the method group to the delegate type will take place, and that delegate will be passed as the parameter to the target method.
You can set a delegate to point to a piece of code, without formally setting that code up as a specific method. Such a piece of code is called an Anonymous Method, and you use the keywords DELEGATE and END-DELEGATE to specify it.
You specify any parameters and return values with the words USING and RETURNING attached to the word DELEGATE.
The following shows how you can attach an anonymous method to the delegate MyDelegate you created in the previous examples:
01 d type MyDelegate.
set d to delegate using s1 as string
returning n1 as binary-long
set n1 to s1::Length
end-delegate.
To invoke a delegate after it has been created, you use the keyword RUN followed by the delegate name, and any parameters enclosed in parentheses. For example, to run the delegate d created above and displaying the results, type:
display [run] d("Hello")
This statement causes the anonymous method to be invoked and return a value of 5. This value is then displayed. Note, run is an optional keyword.
delegate-id MyDelegate.
procedure division using by value s1 as string returning n1 as binary-long.
end delegate.
class-id a.
method-id main static.
01 d type MyDelegate.
01 c type Class1 value new Class1.
set d to method c::m
display run d("ABC")
set d to delegate using s1 as string
returning n1 as binary-long
set n1 to s1::Length
end-delegate
display run d("XYZ")
end method.
end class.
class-id Class1.
method-id m.
procedure division using by value s1 as string returning n1 as binary-long.
set n1 to size of s1 + 3
end method.
method-id m.
procedure division using by value s1 as string s2 as string returning n1 as binary-long.
end method.
end class.
A single delegate can hold references to more than one object/method pair. In such cases, at the time when the delegate is invoked, each one of the methods will be invoked in the order in which they were added to the delegate.
For example:
class-id DelegateCombining.
method-id main static.
01 cd1 type D.
01 cd2 type D.
01 cd3 type D.
01 c type C value new C.
set cd1 to method type C::M1
invoke cd1(-1)
set cd2 to method type C::M2
invoke cd2(-2)
set cd3 to cd2 + method type C::M1
invoke cd3(10)
set cd3 to method type C::M1 + cd3
invoke cd3(20)
set cd3 to cd3 + method c::M3
invoke cd3(30)
set cd3 to cd3 - method type C::M1
invoke cd3(40)
set cd3 to cd3 - method c::M3
invoke cd3(50)
set cd3 to cd3 - method type C::M2
invoke cd3(60)
set cd3 to cd3 - cd2
invoke cd3(60)
set cd3 to cd3 - cd1
try
invoke cd3(70)
catch
display "null reference exception caught"
end-try
set cd3 to cd3 - cd1
set cd1 to method type C::M1
set cd2 to method type C::M2
set cd3 to cd1 + cd2 + cd2 + cd1
invoke cd3(80)
set cd3 to cd3 - cd1
invoke cd3(90)
set cd3 to cd1 + cd2 + cd2 + cd1
set cd3 to cd3 - (cd1 + cd2)
invoke cd3(100)
set cd3 to cd1 + cd2 + cd2 + cd1
set cd3 to cd3 - (cd2 + cd2)
invoke cd3(110)
set cd3 to cd1 + cd2 + cd2 + cd1
set cd3 to cd3 - (cd2 + cd1)
invoke cd3(120)
set cd3 to cd1 + cd2 + cd2 + cd1
set cd3 to cd3 - (cd1 + cd1)
invoke cd3(130)
end method.
end class.
delegate-id D.
procedure division using by value i as binary-long.
end delegate.
class-id C.
method-id M1 static.
procedure division using by value i as binary-long.
display "C::M1 --> " i
end method.
method-id M2 static.
procedure division using by value i as binary-long.
display "C::M2 --> " i
end method.
method-id M3.
procedure division using by value i as binary-long.
display "C::M3 --> " i
end method.
end class.
イベントは、GUI 環境でキーが押されたなどの重要な事象の発生をクラスが通知するための手段です。
イベントを定義するには、キーワード EVENT をデリゲートのフィールドに追加します。次に例を示します。
01 ChangeEvent type ChangeDelegate event public.
同じ型のデリゲート、または互換性のあるメソッド グループや匿名メソッドはイベントにアタッチできます。イベントを所有するクラスがバッキング デリゲートを呼び出す際に、これらは呼び出されます。
イベントとそのバッキング デリゲートの関係は、プロパティとバッキング記憶域の関係に非常に似ています。
You use the ATTACH statement to attach a delegate, method group or an anonymous method to an event:
ATTACH {delegate-instance} TO event-expression
{method-group}
{anonymous-method}
For example:
01 names type myList.
01 MyDelegate type ChangeDelegate.
procedure division.
set names to new myList
attach method ListChanged to names::ChangeEvent
set MyDelegate to method ListChanged
attach MyDelegate to names::ChangeEvent
To detach a delegate or method group from an event use the DETACH statement:
DETACH {delegate-instance} FROM event-expression
{method-group}
For example:
detach MyDelegate from names::ChangeEvent
detach method ListChanged from names::ChangeEvent