(57)【特許請求の範囲】
【請求項１】
コンピュータが、所定の処理を行うオブジェクのメソッドを実行する際に、当該オブジェクトのメソッドを代行するデリゲートを呼び出すことにより、前記所定の処理を実行する方法において、当該方法は、
コンピュータが、所定の戻り値の型及び引数リストを有する第二のメソッド（委譲先メソッド）を有する第二のクラス（委譲先クラス）の第二のインスタンス（委譲先インスタンス）を生成する段階と、
コンピュータが、前記第二のメソッド（委譲先メソッド）と同一の戻り値の型及び引数リストを有する第一のメソッドを備えるデリゲートのインスタンス（デリゲート値）を生成する段階であって、前記第二のインスタンス（委譲先インスタンス）と第二のメソッド（委譲先メソッド）とを指定して前記デリゲートのインスタンスを生成するとともに、前記デリゲートのインスタンスをデリゲート値が割り当てられている変数を使用して表す、前記生成する段階と、
コンピュータが、前記生成されたデリゲートのインスタンスの前記第一のメソッドに引数を渡し呼び出しを行い、更に前記デリゲートのインスタンスの指定する前記第二のインスタンス（委譲先インスタンス）の前記第二のメソッド（委譲先メソッド）の呼び出しを行う段階と、
コンピュータが、呼び出された前期第二のインスタンス（委譲先インスタンス）の前記第二のメソッド（委譲先メソッド）を実行する段階と、
を含み、
前記デリゲートのインスタンスを生成する段階において、前記コンピュータが、前記第二のインスタンス（委譲先インスタンス）の前記第二のメソッド（委譲先メソッド）の戻り値の型及び引数リストを前記第一のメソッドの戻り値の型及び引数リストと照合し、照合できた場合にのみ、前記生成されたデリゲートのインスタンスと前記第一のメソッドを有効かつ実行可能とし、
前記実行する段階において、前記第一のメソッドに渡された引数を前記第二のインスタンス（委譲先インスタンス）の前記第二のメソッド（委譲先メソッド）に渡し、前記第二のメソッド（委譲先メソッド）を実行し、その戻り値を前記デリゲートのインスタンスの前記第一のメソッドの戻り値とすること、を特徴とする方法。
【請求項２】
請求項１に記載の方法において、更に、前記第二のクラス（委譲先クラス）のインスタンスを表す値が割り当てられている変数を使用して、コンピュータが、前記デリゲートのインスタンス生成を行うことを特徴とする方法。
【請求項３】
請求項１に記載の方法において、更に、コンピュータが、前記デリゲートのインスタンスの前記第一メソッドを用いてイベントを処理することを特徴とする方法。
【請求項４】
請求項１に記載の方法において、更に、コンピュータが、１つ又は２つ以上の追加の第二のメソッド（委譲先メソッド）の呼び出しを前記１つ又は２つ以上の追加の第二のメソッド（委譲先メソッド）が合成された１つのデリゲートのインスタンスを呼び出すことで行うことを特徴とする方法。
【請求項５】
請求項４に記載の方法において、更に、コンピュータが、前記１つ又は２つ以上の追加の第二のメソッド（委譲先メソッド）の呼び出しに用いられる呼び出しリスト（委譲先リスト）を保持する、前記１つのデリゲートのインスタンスを作成することを特徴とする方法。
【請求項６】
請求項５に記載の方法において、コンピュータが、更に、新たに第二のメソッド（委譲先メソッド）を前記１つのデリゲートのインスタンスの保持する前記呼び出しリスト（委譲先リスト）に加え、そして、前記１つのデリゲートのインスタンスの保持する前記呼び出しリスト（委譲先リスト）から、前記呼び出しリストに保持されている第二のメソッド（委譲先メソッド）を削除することを特徴とする方法。
【請求項７】
請求項１〜６のいずれか１つに記載の方法において、前記第二のメソッド（委譲先メソッド）がスタティックメソッドであることを特徴とする方法。
【請求項８】
請求項１に記載の方法において、更に、
コンピュータが、前記第二のクラス（委譲先クラス）の第二のインスタンス（委譲先インスタンス）の第二のメソッド（委譲先メソッド）の呼び出しを行う段階において、前記デリゲートのインスタンスは、セキュリティパーミッションのセットを有する別のクラス内にインスタンス生成され、前記第二のクラス（委譲先クラス）はセキュリティパーミッションのセットを有し、前記別のクラスのセキュリティパーミッションのセットが、前記第二のクラス（委譲先クラス）のセキュリティパーミッションのセットと比較され、前記別のクラスが前記第二のインスタンス（委譲先インスタンス）と第二のメソッド（委譲先メソッド）とを指定して前記デリゲートのインスタンスをインスタンス生成させられるかどうかを決定することを特徴とする方法。
【請求項９】
請求項８に記載の方法において、セキュリティチェックを容易にするために、前記第二のクラス（委譲先クラス）の前記第二のインスタンス（委譲先インスタンス）がファイナルクラスであることをコンピュータが、チェックすることを特徴とする方法。
【請求項１０】
コンピュータに、請求項１〜９のいずれか１つに記載の段階の全てを実行させるためのプログラムを記録したコンピュータ読み取り可能な記録媒体。
【請求項１１】
コンピュータに、請求項１〜９のいずれか１つに記載の段階の全てを実行させるためのプログラム。
【発明の詳細な説明】
【０００１】
（著作権表示／許可）
本特許書類の開示の一部は、著作権保護を受けるべき資料を含んでいる。著作権者は、特許・商標局のファイル又は記録に掲載される際に、特許書類又は特許開示の何れかにより複写再生されるのに異存はないが、そうでない場合は全著作権を留保するものである。次の表示は、以下に記載され、図面で表示されているようにソフトウェア及びデータに適用される。
Copyright(c)1998、Microsoft  Corporation、All  Rights  Reserved
【０００２】
（発明の属する技術的分野）
本発明は、一般的にはコンピューター言語、厳密にはオブジェクトベース又はオブジェクト指向言語でプログラミングするための方法及び装置に関する。
【０００３】
（発明の背景）
高級プログラミング言語は、開発者がコードを更に小さなチャンクに分解できるようにする。非オブジェクト指向言語では、分解の最小単位は手続き又は関数である。オブジェクト指向言語では、分解の最小単位は、通常、クラス上のメソッドである。
【０００４】
多くの最新プログラミング言語も、開発者がこれらの分解単位を（やり取りされる、データ構造に保存されるなど）の値として、且つ値が表すコードチャンクを「呼び出す」又は「呼出しする」のに用いられる値として扱えるようにする。異なる言語は異なるメカニズムを提供する。
【０００５】
非オブジェクト指向プログラミング言語において、これらの構造の中で最もよく知られているのは、Ｃ及びＣ＋＋に見られる関数ポインタである。関数型プログラミング言語（ＬＩＳＰ、ＭＬ、スキームなど）では、プログラミングのこのスタイルが一般的である。オブジェクト指向プログラミング言語では、この目的に適したメカニズムは開発されていない。
【０００６】
開発者がメソッドリファレンスを作成及び使用可能なプログラミングシステムとするため、本発明は次の設計目標に取り組む。
【０００７】
ａ）参照すべきメソッドの形状を定義するエンティティを明確にする
ｂ）メソッドに対するリファレンスを入手する
ｃ）このリファレンスを任意のデータ構造に保存する
ｄ）リファレンスを他のパーティにより書き込まれたコードへ送る
ｅ）メソッドリファレンスを保持する者は誰でもメソッドの呼び出しができるようにする
ｆ）メソッドリファレンスの保持者は参照されている目標オブジェクト及びメソッドを決定できるようにする。
【０００８】
更に、本発明のプログラミングシステムは、上記目標を、強く型付けされた方式で達成し、
ａ）開発者が後（実行時）ではなく早期（コンパイル時）にタイプミスマッチ問題を理解できるようにし、
ｂ）開発ツールが、デリゲート(delegate)を用いる要素の形状について開発者に情報を示す、ことができるようする。
【０００９】
（関連する問題に対する従来の解法）
多くの製品が、すべてマイクロソフト社から入手可能なマイクロソフト（登録商標）ビジュアルＣ＋＋、ビジュアルベーシック及びビジュアルベーシックＡのような、Ｃ及びＣ＋＋様の関数ポインタを採用している。ウインドウズ（登録商標）ＡＰＩも関数ポインタを広範囲に利用している。この種の関数ポインタは、以下の複数の理由：
ａ）タイプセーフではなく、キャスティングすることになり、
ｂ）セキュリティを意識しておらず―関数ポインタは、不注意に変えられ、そして呼び出されうるポインタに過ぎず、システムクラッシュに至り、
ｃ）目標オブジェクト及びメソッドへのアクセスを考慮していない、ものであって不完全である。
【００１０】
マイクロソフト（登録商標）Ｊａｖａ ＶＭ及び関連製品は、メソッドリファレンスの原型を提供する「Ｊａｖａコアリフレクション」システムを有する。開発者はｊａｖａ．ｌａｎｇ．ｒｅｆｌｅｃｔ．Ｍｅｔｈｏｄのインスタンスを入手できる。このインスタンスは、メソッドをレイトバインド方式で呼び出すのに用いることができる。このリファレンスの形式は本質的にレイトバインド(late-bound)で、そのため非能率的である。
【００１１】
（発明の概要）
本発明の一つの実施例によれば、あるクラスのあるインスタンスの第二メソッドを呼び出すことにより第一メソッドを呼び出す段階をコンピューターを使って実行する、オブジェクトベースのコンピューターコードでコンピューターをプログラミングするための方法が提供されており、第二メソッドに供給されるパラメータは第一メソッドに供給され、第二メソッドのパラメータリストは第一メソッドのパラメータリストに一致し、更に第一メソッドは名前により、そして第一メソッドのパラメータリスト及び結果のタイプをクラスに対して宣言されたパラメータリスト及び結果のタイプと突き合わせることにより識別される。
【００１２】
別の特徴によれば、クラスのインスタンスは、変数に割り当てることができ一つの手続きから別の手続きへ送ることができる値により表示され、プログラムコードは、クラスのインスタンスを示す値を割り当てられた変数上の第二メソッドを呼び出すのに用いられる。
【００１３】
別の実施例では、セキュリティに関するパーミッションは、オブジェクトベースのプログラム内の各クラスと関連しており、これらのパーミッションは、第一メソッドによる第二メソッドへの呼び出しが許可されるかどうか決定するのに用いられる。
【００１４】
更に別の実施例では、第一メソッドは、第一クラスの宣言で自動的に作成される。
【００１５】
更に別の実施例では、第一メソッドは、オブジェクトベースのプログラムのイベントを処理するのに用いられる。
【００１６】
更に別の実施例では、１つ又はそれ以上の追加の第一メソッドは第二メソッドへの呼び出しを使って呼び出され、そこでは、１つ又はそれ以上の対応する追加のパラメータのセットが、それぞれ、もう一つの追加の第一メソッドに供給される第二メソッドに供給される。更に、呼び出しリストは第二メソッドと関連しており、呼び出しリストは呼び出される第一メソッドを特定する。また、第一メソッドが呼び出しリストに加えられることもあるし、呼び出しリストから削除されることもある。
【００１７】
更に別の実施例では、既に上に概要を述べた方法が、コンピュータープログラムと、コンパイラーと、インタープリターと、ハードウェア及びソフトウェアを含むプログラミングシステム内に組み込まれている。
【００１８】
（発明の詳細な説明）
好適な実施例に関する以下の詳細な説明では、その一部を形成する添付図面を参照し、本発明が実施される特定の実施例を示すことにより説明を行う。本発明の範囲から逸脱することなく、他の実施態様を利用したり、構造的な変更を行えることは理解されるであろう。
【００１９】
（序論）
本発明は、本明細書で「デリゲート(delegate)」と名付けられている、オブジェクトベースのプログラミング内でメソッドを参照するためのメカニズムを提供する。関数ポインタは関数へのリファレンスを含み、一方デリゲートはメソッドへのリファレンスを含んでいる。両者は、関数ポインタが１つのリファレンス（関数）しか含んでいないのに対して、デリゲートはオブジェクト及びオブジェクトのメソッドへのリファレンスを含む点で異なっている。
【００２０】
本明細書に記載のデリゲートの有益な特性は、デリゲートが参照するオブジェクトのタイプ（クラス）について知らないか又は留意しないということである。むしろ、重要なのは、参照されるメソッドのパラメータリストがデリゲートと互換性があることである。このことは、デリゲートを呼び出す呼び出し人が何のクラス又はメンバーが呼び出されているのか正確に知る必要がなく「匿名」通知利用に関してデリゲートを非常に有益なものにする。
【００２１】
デリゲートは関数ポインタと同様に値である。他の値のように、変数に割り当てることができ、一つの手続きから別の手続きへ送ることもできる。デリゲートも、利用し、適用し、呼び出すことができる。この操作を実行するときには、ゼロ又はそれ以上の引き数がデリゲートに送られる。
【００２２】
デリゲートは安全である、即ち強く型付けされた(strongly typed)ものであるという点で関数ポインタと異なる。更に、関数ポインタは文脈自由であり、つまり、関数が関数ポインタを通じて呼び出されるときには、関数はパラメータを通じて送られてくる以外の文脈(context)を持っていないのに対し、デレゲイトはそれ自身文脈を伴っている。メソッドがデレゲイトを通じて呼び出される場合は、呼び出しはデレゲイトにより参照されるオブジェクトに起こり、従って既知の文脈を使ってメソッドが提供される。
【００２３】
以下に更に詳しく説明するが、本発明は、図１に示すように多数の異なる形式を取る。図１に示すように、本明細書に記載されているデリゲートの実施例は、プログラミング言語１０と、コンピュータープログラム１２と、コンパイラ１４と、Ｊａｖａバーチャルマシンインタープリタソフトウェア１６と、イベントモデル１８の形態で実施される。図２に示されているように、これら様々な実施例は、例えばこれに限定するわけではないが、ＩＢＭ互換パーソナルコンピューター等の（例えばこれに限定するわけではないが、ＣＰＵ、記憶装置、メモリ、キーボード、マウス等の従来のコンピューター構成要素を含む）コンピューターシステム２０上で実行し、保存することができるか、そうでなければ、ハードドライブ２２、フロッピーディスク２４、ＣＤ−ＲＯＭ２６又は電子データトランスミッション２８のような様々な担体媒体上で機械読み取り可能な形式で具体化することができる。
【００２４】
（本発明のＪ＋＋での実施例）
本発明の次の実施例は、マイクロソフト社のマイクロソフト（登録商標）ビジュアルＪ＋＋、バージョン６．０におけるデリゲートのインプリメンテーションについて説明している。しかし、本発明は、決してＪ＋＋言語に限定されるものではなく、Ｃ＋＋のようなどんなオブジェクト指向プログラミングシステム又はマイクロソフト（登録商標）ビジュアルベーシックのようなオブジェクトベースプログラミングシステムにも広く適用できる。本明細書では「オブジェクト指向」という用語は、オブジェクトベースのプログラミング言語及び継承が提供されるプログラミング言語の両方を意味する。「オブジェクトベース」という用語は、マイクロソフト（登録商標）ビジュアルベーシックのように、コードがオブジェクトの中に編成されるが、必ずしも継承を提供するわけではないプログラミング言語を指す。
【００２５】
本発明を詳細に述べる前に、デリゲートを使っているＪ＋＋コンピュータープログラム３０の簡単な例が図３に示されており、そこではデリゲートインスタンスがインスタンス上のメソッドをカプセル化している。この場合、メソッド「ｈｅｌｌｏ」はデリゲート「ｆ」を使って呼び出される。更に、デリゲートの宣言は、デリゲートがカプセル化可能であるメソッドの種類を定義する。
【００２６】
図３のプログラム例は、デリゲートのインスタンスｆであるSimpleDelegateがどのようにインスタンス生成されて（“f＝new  SimpleDelegate（o．hello）”）、次にどのように呼び出されるか（“f．invoke（）”）を示している。以下に更に詳しく説明するが、有効且つ実行可能であるために、SimpleDelegateデリゲートのタイプは参照される「hello」メソッドのタイプと一致していなければならない。この場合、helloとSimpleDelegateは共に、入力パラメータを必要とせず、ボイド出力である。これも以下に説明するが、この要件はデリゲートをタイプセーフにする。
【００２７】
以下に述べるのは、マイクロソフト（登録商標）ビジュアルＪ＋＋、バージョン６．０において実行されている、J＋＋言語の延長として、デレゲイトの説明である。サンマイクロシステムズ社より発行されているＪａｖａ言語仕様を参考資料として本明細書に援用する。Ｊａｖａ言語仕様は、本明細書では「ＪＩＬ」とも呼んでおり、一部ではその様に引用する。
【００２８】
（Ｊ＋＋実施例におけるデレゲイト宣言）
本明細書に述べられている本発明の実施例によるデリゲート宣言は、デリゲート又はマルチキャストデリゲートのどちらかから来る新しいクラスを指定する。
デリゲート宣言は、
DelegateModifiersopt  delegate ResultType Identifier
(FormalParameterListopt)Throwsopt
の形態を取る。
【００２９】
クラス宣言に対する関連プロダクションは、
ClassModifiersopt  class Identifier Superopt Interfaceopt ClassBody
である。
【００３０】
本例のＪａｖａ言語文法を使って宣言される場合、デリゲート宣言は、次の属性を有するクラスになる。
１）ClassModifiersoptに対し、クラス宣言はDelegateModifiersopt を有し 、所定の文脈内で指定される前提で、static、finalという追加変更が加わる。
２）Identifierに対し、クラス宣言は、デリゲート宣言のIdentifierを有する。
３）Superoptに対しては、multicast変更子が指定されれば「extends  com．ms.lang．MulticastDelegate」を有し、multicast変更子が省略されれば「extends  com．ms.lang．Delegate」を有する。
４）Interfaceoptに対しては、“”を有する。
【００３１】
デリゲートが完全修飾された名前Ｐ（ＪＬＳの§６．７参照）を使って名前の付いたパッケージ（ＪＬＳの§７．４．１参照）で宣言されれば、デリゲートは完全修飾された名前Ｐ．Identifierを有することになる。デリゲートが名前無しパッケージ（ＪＬＳの§７．４．２参照）で宣言されれば、デリゲートは完全修飾された名前Identifierを有することになる。図４の例では、デリゲートEmptyMethod（３２）は、パッケージステートメントの無いコンパイル単位で宣言され、従ってEmptyMethodが完全修飾された名前であるのに、図５Ａの例コード３４では、デリゲートEmptyMethodの完全修飾された名前はvista.EmptyMethodである。
【００３２】
本発明の本実施例では、コンパイラ１４（デジタル計算プラットフォームで実行可能）は、
１）デリゲートに命名する識別子が、同一パッケージ（ＪＬＳの§７．６参照）で宣言される他のデリゲートタイプか、クラスタイプか、又はインターフェースタイプの名前として現れる場合、又は、
２）デリゲートに命名する識別子が、デリゲート宣言を含むコンパイル単位（ＪＬＳの§７．３参照）内の、シングルタイプインポート宣言（ＪＬＳの§７．５．１参照）によるタイプとして宣言されている場合、
コンパイル時エラーを発生させる。
【００３３】
（デリゲートタイプの名前の範囲）
デリゲート宣言内の識別子は、デリゲートの名前を指定する。このデリゲートの名前は、その範囲として（ＪＬＳの§６．３参照）デリゲートが宣言される完全なパッケージを有する。
【００３４】
（デリゲート変更子）
デリゲート宣言はデリゲート変更子(delegate modifier)を含んでいてもよい。
DelegateModifiersは、ゼロであるか、或いは
ｐｕｂｌｉｃ    ｐｒｉｖａｔｅ    ｓｔａｔｉｃ    ｆｉｎａｌ
ｍｕｌｔｉｃａｓｔ
の中の１つであってもよい。
【００３５】
２つ以上のデリゲート変更子がデリゲート宣言内に現れる場合は、それらは通常、要求されてはいないが、DelegateModifierに対するプロダクションの中で先に述べたことと一致するオーダで現れる。
【００３６】
ｍｕｌｔｉｃａｓｔ変更子を含むデリゲート宣言は、ボイドであるResultTypeを有していなければならず、そうでなければコンパイルエラーが生じる。
【００３７】
アクセス変更子ｐｕｂｌｉｃは、ＪＬＳの§６．６で論じられている。本発明のこの実施例のコンパイラは、
１）２つ以上のデリゲート変更子が用いられる場合、
２）同じ変更子がデリゲート宣言に二度以上現れる場合か、又はデリゲート宣言が２つ以上のアクセス変更子ｐｕｂｌｉｃ及びｐｒｉｖａｔｅを有する場合、
３）ｐｒｉｖａｔｅ変更子が、クラス内にネストされていないデリゲート宣言内に現れる場合、
コンパイル時エラーを生み出す。
【００３８】
デリゲートは、暗黙にｓｔａｔｉｃである。デリゲート宣言内で変更子ｓｔａｔｉｃを重複して指定することは許されるが、スタイルの問題としては非常に妨げとなる。更に、デリゲートは暗黙にｆｉｎａｌである。デリゲート宣言内で変更子ｆｉｎａｌを重複して指定することは許されるが、スタイルの問題としては非常に妨げとなる。
【００３９】
本発明の実施例によれば、デリゲート定義は、クラス定義が現れるところならどこでも現れる。クラス定義同様に、デリゲート定義はクラス定義内にネストすることができる。加えて、デリゲートは常にトップレベルである。
【００４０】
デリゲートのメンバーは、ベースクラス（デリゲート又はマルチキャストクラスのどちらか）から継承したメンバーと、カプセル化されたメソッドを呼び出すのに用いることのできる自動的に作成された特別なｉｎｖｏｋｅメソッド（以下に記載）とを含む。デリゲート宣言も、自動的に生み出された特別なコンストラクタ(constructor)を備えたクラスに帰着する。
【００４１】
（呼び出しメソッド）
デリゲートのメンバーは、自動的に作成され、カプセル化されたメソッドを呼び出すのに用いることができるｉｎｖｏｋｅメソッドを含む。ｉｎｖｏｋｅメソッドのシグネチャ及びリターンタイプは、デリゲート宣言により決定される。特に、ｉｎｖｏｋｅメソッドのシグネチャは、
ResultType  ｉｎｖｏｋｅ(FormalParameterListopt)Throwsopt
であり、ResultTypeと、(あれば) FormalParameterListと、(あれば) Throwsとはデリゲート宣言のシグネチャである。
【００４２】
（デリゲートインスタンス生成）
デリゲートは次のような２つのコンストラクタを有する。
１）形状が、Ｄｅｌｅｇａｔｅベースクラスにより定義される「インスタンス」コンストラクタ。このコンストラクタへの引き数と、Ｏｂｊｅｃｔメソッドの名前とＳｔｒｉｎｇメソッドの名前とは、デリゲートのタイプと組み合わされて、デリゲート定義と一致する指示されたオブジェクト上に、独自にメンバーを特定する。新たに構成されたデリゲートは、このメソッドをカプセル化する。
２）ほとんどのメソッド解決が、実行時ではなくコンパイル時になされることを可能にする特定の「メソッド指示子」コンストラクタ。メソッド指示子デリゲートは、Ｊａｖａコアリフレクションを通じて表に出されない。
【００４３】
クラス及びインスタンスコンストラクタは何も特別ではなく、それらは本明細書に述べられているベースＤｅｌｅｇａｔｅクラスの説明に詳細に論じられている。メソッド指示子式は、デリゲートインスタンス生成を目的に、クラス又はインスタンスメソッドを示すのに用いられる。
【００４４】
クラスインスタンス生成式は、
newClassType（ArgumentListopt）
DelegateInstantiationExpression
の形を取る。
デリゲートインスタンス生成式は、
NewDelegateTupe（MethodDesignator）
の形を取る。
メソッド指示子は、
MethodName
Primary.  Identifier
Super．  Identifier
の形を取る。
デリゲートタイプは、com．Ms．lang．Delegateから出てくるクラスである。
【００４５】
メソッド指示子は、メソッドを指示するには十分ではない。メソッドのセットを（潜在的に）指定するのではなく、特定のメソッドを指示するためには、メソッド指示子によってインスタンス生成されるデリゲートのリターンタイプ及びシグネチャ（引き数の数及びタイプ）を参照することが必要である。このため、メソッド指示子及び新しいインスタンス仕様形態が、単一の単位として記述される。
【００４６】
デリゲートインスタンス生成には、メソッド呼び出し式（ＪＬＳの§１５．１１参照）に関する探索ルールと同じ様な探索ルールが使われる。メソッドを指示することは、メソッドがオーバーローディングとなったりインスタンスメソッドがオーバーライディング(overriding)となる可能性があるために、複雑である。メソッド呼び出し式により呼び出されるメソッドを決定するのには、複数の追加段階が含まれている。以下に述べるのは、本発明の本実施例による、コンパイル時及び実行時共にデリゲートインスタンス生成に含まれる段階である。
【００４７】
（アーリーバインド及びレイトバインドデリゲート）
図３の例で、インスタンス生成「f=new SimpleDelegate（o.hello）」はメソッド「hello」がコンパイル時に知らされるアーリーバインドデリゲートである。ある場合には、デリゲートが結合されるべきメソッドは、プログラムがコンパイルされているときには知られていない。例えば、対話式開発環境のユーザーは、プログラムプロトタイピング用のメソッドの名前を特定するかもしれないし、呼び出されるメソッドの名前を何か他の様式で計算するか又は入力するかもしれない。この場合、２つの引き数コンストラクタを使うことにより、デリゲートのインスタンスを構築することができる。
【００４８】
コンストラクタの第一引き数は、オブジェクトでメソッドが呼び出されることになるオブジェクトを指定する。コンストラクタの第二引き数は、メソッドの名前を指定する。第一引き数で指定されたオブジェクトは、そのオブジェクトが指示された名前のメソッドを有することを確認するために、デリゲートクラスが宣言されたと同じシグネチャ（すなわちリターンタイプ及び引き数タイプ）使って照合される。照合ができなければ、例外が起こる。照合されれば、新しいデリゲートブジェクトが構築されて戻される。
【００４９】
直ぐ上に述べたように、「レイトバインド」デリゲートのインスタンス生成は、例えば「ｇ=new  SimpleDelegate（o,“hello”）、」の形を取り、ここでメソッド「hello」はプログラム実行の間に定められるストリングである。レイトバインドデリゲートの場合、呼び出しは「g.dynamicInvoke（Object〔〕args）」の形を取る。図５Ｂのプログラム例３６は、ストリングメソッドの名前に基づいてレイトバインドデリゲートを構築する。
【００５０】
（コンパイラオペレーション）
先に述べたように、本発明の実施例はコンパイラ１４を含む。デリゲートインスタンス生成式をコンパイル時に処理するには、数段階が必要である。第一に、コンパイラは検索するクラス又はインターフェースを決定しなければならない。第二に、コンパイラは一致していてアクセス可能なメソッドを検索しなければならない。第三に、コンパイラは、メソッドが適当かどうかチェックしなければならない。これらのプロセスについては、以下に更に詳細に説明する。
【００５１】
（コンパイル時段階１：検索するクラス又はインターフェースの決定）
コンパイル時にデリゲートインスタンス生成式を処理する際の第一段階は、メソッドの名前、及びその名前のメソッドの定義に対してチェックすべきクラス又はインターフェースを計算することである。メソッド指示子の形式によっては、次のように考えられるケースが幾つかあり、
１）形式がMethodNameであれば、２つのサブケースがあり、
ａ）シンプルな名前、即ち、まさにIdentifierであれば、メソッドの名前はIdentifierであり、検索するクラス又はインターフェースは、その宣言がメソッド指示子を含んでいるクラス又はインターフェースである。
ｂ）他のすべてのケースでは、修飾された名前はFieldName. Identifierの形を有しており、メソッドの名前はIdentifierであり、検索するクラス又はインターフェースはFieldNameの名前が付いているフィールドの宣言されたタイプである。
２）形式がPrimay.Identifierであれば、メソッドの名前はIdentifierであり、検索されるクラス又はインターフェースはPrimay式のタイプである。
３）形式がｓｕｐｅｒ．Identifierであれば、メソッドの名前はIdentifierであり、検索されるクラスは、その宣言がデリゲートインスタンス生成を含むようなクラスのスーパークラスである。そのようなメソッド指示子がインターフェース内か、クラスｏｂｊｅｃｔ内か、ｓｔａｔｉｃメソッドか、スタティックイニシャライザか、又はｓｔａｔｉｃ変数に関するイニシャライザかの内かに生じれば、コンパイル時エラーが生じる。次に、この形態のメソッド指示子は、ｏｂｊｅｃｔ以外のクラス内と、インスタンスメソッドの本体か、コンストラクタの本体か、又はインスタンス変数に関するイニシャライザかの内にだけ現れることになる。
【００５２】
（コンパイル時段階２：メソッドシグネチャの決定）
第二段階は、メソッド宣言のために前の段階で決定されたクラス又はインターフェースを検索する。この段階は、一致し、且つアクセス可能であるメソッド宣言、即ち、インスタンス生成されるデリゲートのタイプに一致し、デリゲートインスタンス生成文脈から正しく呼び出すことのできる宣言の位置を突き止めるために、指示されたメソッドの名前及びデリゲート定義正式パラメータのタイプを用いる。突き合わせルールは厳密なので、そのようなメソッド宣言は１つだけしかない。
【００５３】
メソッドは、デリゲートタイプに一致するかしないかのどちらかである。メソッドＭがタイプＴに一致し、且つ一致する場合にだけ、メソッドＭをカプセル化するタイプＴのデリゲートインスタンスをインスタンス生成することが可能である。
【００５４】
Ｍをメソッド、Ｔをデリゲートのタイプとしよう。次のことがすべて真であり且つ次のことにすべてが真である場合だけ、ＭはＴに一致する。
１）ＭとＴは正式なパラメータの同じ数字を有し、
２）Ｍの各パラメータのタイプは、Ｔのパラメータのタイプと一致し、
３）Ｍの結果タイプは、Ｔの結果タイプと一致し、
４）ＭはＴ以上にもっとチェックされた例外を投じるように宣言されてはいない。Ｍが、何らかのチェックされた例外タイプについて述べるｔｈｒｏｗクローズを含んでいれば、Ｔはｔｈｒｏｗクローズを含んでいなければならず、ｔｈｒｏｗクローズ内に挙げられている全てのチェックされた例外タイプに対し、その同じ例外クラス又はそのスーパークラスの中の一つがＴのｔｈｒｏｗクローズ内に生じなければならない。
【００５５】
突き合わせルールは厳密な一致（パラメータリスト及びリターンタイプに対し同じタイプ）を要求するので、何れの所定のターゲットに対しても一致するメソッドは多くとも１つしかあり得ないことに留意されたい。
【００５６】
本明細書に記載のプロセスにより決定されるクラス又はインターフェースは、デリゲートタイプに一致するメソッド宣言を求めて検索され、スーパークラス及びスーパーインターフェースから継承されるメソッド定義は、この検索に含まれている。メソッド宣言がメソッド呼び出しにアクセス可能かどうかは、メソッド宣言内のアクセス変更子（public、無し、protected、又はprivate）及びメソッド指示子が現れる場所による。クラス又はインターフェースが、一致し、且つアクセス可能であるメソッド宣言を持っていなければ、コンパイル時エラーが発生する。
【００５７】
（コンパイル時段階３：選択されたメソッドは適切か？）
デリゲートインスタンス生成式に対し一致し且つアクセス可能なメソッド宣言がある場合、これはデリゲートインスタンス生成式に対するコンパイル時宣言と呼ばれる。コンパイル時宣言に、更に複数のチェックがなされなければならない。コンパイル時エラーは、
１）メソッド指示子が、Identifierの形態のMethodNameを有し、且つメソッド指示子がｓｔａｔｉｃメソッドか、スタティックイニシャライザか又はｓｔａｔｉｃ変数用イニシャライザ内に現れる場合、
２）メソッド指示子が、TypeName.Identifierの形態のMethodNameを有する場合、に発生する。
【００５８】
次のコンパイル時情報は、実行時に用いるメソッド呼び出しと関連する。
１）コンパイル時宣言へのリファレンス（メソッド）。
２）コンパイル時宣言を含むクラスまたはインターフェース（ターゲット）。
３）次のように計算される呼び出しモード、
ａ）コンパイル時宣言がｐｒｉｖａｔｅ．変更子を有し、呼び出しモードがｎｏｎｖｉｒｔｕａｌである場合。
ｂ）さもなければ、左かっこ前のメソッド呼び出し部分がｓｕｐｅｒ．Identifierの形態であり、呼び出しモードがｓｕｐｅｒである場合。
ｃ）さもなければ、コンパイル時宣言がインターフェース内にあり、呼び出しモードがｉｎｔｅｒｆａｃｅである場合。
ｄ）さもなければ、呼び出しモードがｖｉｒｔｕａｌである場合。
【００５９】
（実行時オペレーション）
本発明は、本発明のデリゲートを実行するために、更にＪａｖａバーチャルマシンインタープリタソフトウェア１６（図１）を提供する。実行時にデリゲートインスタンス生成式を処理するためには数段階が必要である。第一に、コンパイラはターゲットのタイプ及びメソッドのアクセス可能性をチェックしなければならない。第二に、コンパイラは、インスタンスメソッドがオーバーライディングする可能性を考慮に入れながら、呼び出すメソッドの位置を突き止めなければならない。
【００６０】
（実行時段階＃１：タイプ及びメソッドのアクセス可能性のチェック）
コンパイル時に決定されるように、Ｃをデリゲートインスタンス生成式を含むクラス、Ｔをデリゲートインスタンス生成式に対するコンパイル時宣言を含んだクラス又はインターフェース、ｍをメソッドの名前とする。
【００６１】
Ｊａｖａバーチャルマシンインタープリタソフトウェア１６は、リンケージ部分として、メソッドｍがタイプＴ内にまだ存在することを保証する。これが真でない場合は、（RuntimeExceptionのサブクラスである）ＩｌｌｅｇａｌＡｒｇｕｍｅｎｔＥｘｃｅｐｔｉｏｎが生成される。呼び出しモードがｉｎｔｅｒｆａｃｅの場合、バーチャルマシンソフトウェア１６は、ターゲットリファレンスタイプがまだ特定化されたインターフェースを実行することもチェックしなければならない。ターゲットリファレンスタイプがインターフェースをまだ実行していなければ、ＩｎｃｏｍｐａｔｉｂｌｅＣｌａｓｓＣｈａｎｇｅＥｒｒｏｒが生成される。
【００６２】
バーチャルマシンソフトウェア１６は、リンケージの間に、タイプＴとメソッドｍがアクセス可能であることも保証しなければならない。
【００６３】
タイプＴに関しては、
１）ＴがＣと同じパッケージ内にある場合、Ｔはアクセス可能である。
２）ＴがＣと異なるパッケージ内にあり、Ｔがｐｕｂｌｉｃである場合、Ｔはアクセス可能である。
メソッドｍに関しては、
１）ｍがｐｕｂｌｉｃである場合、ｍはアクセス可能である。（インターフェースの全メンバーはｐｕｂｌｉｃである（ＪＬＳの§９．２参照））。
２）ｍがｐｒｏｔｅｃｔｅｄである場合、ｍは、ＴがＣと同じパッケージ内にあるか又はＣがＴ又はＴのサブクラスである場合及びその場合にだけアクセス可能である。
３）ｍがデフォルト（パッケージ）アクセスを有する場合、ｍは、ＴがＣと同じパッケージ内にある場合及びその場合にだけアクセス可能である。
４）ｍがｐｒｉｖａｔｅである場合、ｍは、ＣがＴである場合及びその場合にだけアクセス可能である。
Ｔ又はｍの何れかがアクセス不可能である場合、ＩｌｌｅｇａｌＡｒｇｕｍｅｎｔＥｘｃｅｐｔｉｏｎ（ＪＬＳの§１２．３参照）が生成される。
【００６４】
（実行時段階＃２：呼び出すメソッドの位置確認）
メソッド探索に関する戦略(strategy)は、呼び出しモードによって異なる。本発明の実施例では、デリゲートのあるスタティックメソッドをカプセル化することは不可能で、従ってインスタンスメソッドがデリゲートによりカプセル化されるべきことが明白であり、ターゲットリファレンスが存在する。ターゲットリファレンスがｎｕｌｌである場合、このポイントにＮｕｌｌＰｏｉｎｔＥｘｃｅｐｔｉｏｎが投入される。そうでなければ、ターゲットリファレンスは、ターゲットオブジェクトを参照するよう告げられ、デリゲートが呼び出されるときに、キーワードｔｈｉｓの値として用いられる。呼び出しモードに関する他の４つの可能性は、次に、Ｊａｖａバーチャルマシンインタープリタソフトウェア１６により以下のように考慮される。
【００６５】
呼び出しモードがｎｏｎｖｉｒｔｕａｌである場合、オーバーライディングは許されない。クラスＴのメソッドｍは呼び出されるものである。そうでなければ呼び出しモードはｉｎｔｅｒｆａｃｅ、ｖｉｒｔｕａｌ又はｓｕｐｅｒであり、オーバーライディングが生じるかもしれない。ダイナミックメソッド探索が用いられる。ダイナミック探索プロセスはクラスＳからスタートして、以下のように決定される。
１）呼び出しモードがｉｎｔｅｒｆａｃｅ又はｖｉｒｔｕａｌの場合、Ｓは最初はターゲットオブジェクトの実際の実行時クラスＲである。ターゲットオブジェクトがアレイである場合、ＲはクラスＯｂｊｅｃｔである（呼び出しモードｉｎｔｅｒｆａｃｅに対しては、必ずＲがＴを実行し、呼び出しモードｖｉｒｔｕａｌに対しては、必ずＲがＴ又はＴのサブクラスの何れかであることに留意のこと）。
２）呼び出しモードがｓｕｐｅｒである場合、Ｓは最初はデリゲートインスタンス生成を含むクラスＣのスーパークラスである。
【００６６】
ダイナミックメソッドの探索には、メソッドｍに関して、クラスＳと、必要ならば次にクラスＳのスーパークラスを検索するために次の手続きを用いる。
１）クラスＳが（上記）コンパイル時に決定されたメソッド呼び出しに必要な同じ記述子（同数のパラメータ、同じパラメータタイプ、同じリターンタイプ）を使ってｍと名付けられているメソッドについての宣言を含んでいる場合には、これがデリゲートによりカプセル化されるべきメソッドであり、手続きは終了する。
２）そうでなくて、ＳがＴでない場合、この探索の結果がどう出ようと、この同一の探索手続きはＳのスーパークラスを使って実行される。
【００６７】
この手続きは、クラスＴに達するとき、適したメソッドを見つけ出すことになるが、なぜなら、そうでなければ上記のチェックによりＩｌｌｅｇａｌＡｃｃｅｓｓＥｘｃｅｐｔｉｏｉｎが投入されることになるからである。ダイナミック探索プロセスは、ここでは明示的に記載されているが、しばしば暗黙的に実施されることに留意しておくべきである。
【００６８】
（実行時段階＃３：セキュリティチェック）
ここで述べるデリゲートの実施例では、デリゲートは信頼されている（以降、信頼）コードを破壊するためには用いられないことを保証するための手続きが提供されている。特別なセキュリティ予防対策がなければ、信頼されていない（以降、非信頼）メソッドがデリゲートを使って、非信頼クラスがコールスタックに現れないような様式で、信頼メソッドを呼び出す可能性がある。標準的なＪａｖａセキュリティの下では、コールスタックに非信頼メソッドがない場合は、信頼メソッドはうまく行くし、新しい非信頼メソッドがコールスタックにある場合は、おそらく失敗することになる。良い例がｊａｖａ．ｉｏ．Ｆｉｌｅ．ｄｅｌｅｔｅであり、非信頼コードがこのメソッドを呼び出そうとすれば、SecurityExceptionが投入される。しかし、非信頼コードがこの信頼メソッドをデリゲート内にカプセル化し、完全な信頼コードに送って、デリゲートを呼び出す場合は、メソッド（ｊａｖａ．ｉｏ．Ｆｉｌｅ．ｄｅｌｅｔｅ）はうまく行くであろう。従って、ここに述べる本実施例は、以下に論じるように、デリゲートをインスタンス生成する際に特定のセキュリティチェックを実行する。このセキュリティチェックは実行時に行われる。
【００６９】
ここに述べられている本発明の実施例は、標準Ｊａｖａセキュリティモデルを拡張して、セキュリティパーミッションのセットを全てのＪａｖａクラスと関係付けている。所与のクラスに対して、関係付けられたセキュリティパーミッションのセットが、クラスのメソッドが実行を許される（ファイルＩＯ及び印刷のような）信頼オペレーションを決定する。非信頼クラスは空のパーミッションセットを有し、一方、完全信頼クラスは完全なパーミッションセットを有する（すなわち、すべてのパーミッションを有する）。
【００７０】
実行時にうまく行くデリゲートインスタンス生成に関しては（デリゲートインスタンス生成式を含むクラス）Ｃのパーミッションは、実行時に決定される、メソッドｍを含むクラスに所有されているパーミッションのスーパーセットでなければならない。これに当てはまらなければ、ＩｌｌｅｇａｌＡｃｃｅｓｓＥｘｃｅｐｔｉｏｎが投入される。更に、このセキュリティチェックは、デリゲート又はマルチデリゲートクラスから出されるクラスがファイナルであることを要求して、コールチェーンを探索させ、どのエンティティがデリゲートを作成するのかを調べさせる。結果として、非信頼クラスは非信頼メソッドにデリゲートを作成するだけで、完全信頼クラス（即ちシステムクラス）はアクセス可能な何れのメソッドにも作成できる。
【００７１】
（コンパイラ対インタプリタアクティビティ）
上記のように、コンパイラ１４とインタプリタソフトウェア１６とは別々のソフトウェア構成要素である。しかし、これらの構成要素は、オペレーションのモードによって、ある場合には、結合デリゲートのような同じ機能を実行することもある。更に、コンパイラ１４とインタプリタソフトウェア１６の機能は、ある場合には、互いに交換されたり又は共有されたりすることがある。従って、本発明は、ここに記載の実施例に述べられている機能の特定の分割には決して限定されるものではない。むしろ、コンパイラ１４とインタプリタソフトウェア１６とは、オブジェクトベースのコンピュータコードを処理してコンピュータによる実行に備えるという共通のタスクを共有するものとして考えられるべきである。
【００７２】
（クラスｃｏｍ．ｍｓ．ｌａｎｇ．Ｄｅｌｅｇａｔｅ）
上記のように、すべてのデリゲートはこのベースデリゲートクラスから出る。タイプＤｅｌｅｇａｔｅのオブジェクトは、呼び出し可能なエンティティ、すなわちインスタンス及びインスタンス上のメソッドをカプセル化する。クラスＤｅｌｅｇａｔｅの定義例３８を図６に示す。
【００７３】
保護されているＤｅｌｅｇａｔｅ（Object target、String methodName）コンストラクタは、新たに作成されるＤｅｌｅｇａｔｅオブジェクトが、引き数により特定されるターゲット及びメソッドをカプセル化するように初期化する。ｔａｒｇｅｔがヌルの場合、NullPointerException例外が浮上する。methodNameの引き数は、先に定義されているように、一致していて、アクセス可能で、適切なメソッドを指示しなければならない。一致するターゲットメソッドが見付けられない場合、IllegalArgumentException例外が実行時に投入される。メソッドが見付けられない場合は、NoSuchMethodErrorが投入される。
【００７４】
引き数が、ｎｕｌｌではなく、このＤｅｌｅｇａｔｅオブジェクトと同じターゲットメソッド及び呼び出しリストを有するＤｅｌｅｇａｔｅオブジェクトである場合及びその場合にだけ、public  final  boolean  equals（Object  obj）の結果は真である。２つのデリゲートは、Ｄｅｌｅｇａｔｅ．ｅｑｕａｓにより定められているように、互いに等しくなるために同じタイプである必要はない。この式はオブジェクトのｅｑｕａｌｓメソッドを無効とする（ＪＬＳの§２０．１．３参照）。
【００７５】
式public  static  final  Delegate  combine（Delegate  a、Delegate  b）は、所与の２つのデリゲートを組み合わせて単一のデリゲートを形成する。ａとｂが共にヌルの場合、結果はヌルである。ａかｂのどちらかがヌルの場合、結果はヌルでないデリゲートである。ａとｂが共にヌルでない場合、結果は、ａの呼び出しリストとｂの呼び出しリストをその順に連結させることにより形成される呼び出しリストを備えた新しいデリゲートである。呼び出しリストが、同じオブジェクト上の同じメソッドを参照する重複エントリーエントリを含むことは、エラーとはみなされない。ａとｂが共にヌルでない場合、デリゲートａとデリゲートｂは、同じ実タイプでなければならない。そうでない場合には、IllegalArgument  Exception例外がコンパイラ１４により投入される。ａとｂが共にヌルでない場合、デリゲートａとデリゲートｂは、クラスMulticastDelegateから出る実タイプでなければならない。そうでない場合、Multicast  NotSupportedException例外がコンパイラ１４により投入される。
【００７６】
式public  static  final  Delegate  combine（Delegate〔〕delegate）は、各デリゲートの呼び出しリストをデリゲートアレイ内に順に連結して構成された呼び出しリストを備えたデリゲートを戻す。結果としての呼び出しリストが空である場合、回答はヌルである。デリゲートアレイはヌルエントリを含んでいてもよいが、そのようなエントリは無視される。デリゲートアレイパラメータがヌル又は空である場合、結果はヌルである。デリゲートアレイのヌルでない構成要素は、同じ実タイプでなければならない。さもなければIllegalArgumentException例外が投入される。デリゲートアレイ内に複数のヌルでない構成要素がある場合には、これらの構成要素はクラスMultiDelegateから出る実タイプでなければならない。さもなければ、MulticastNotSupportedException例外がコンパイラ１４により投入される。
【００７７】
式public  static  final  Delegate  remove（Delegate  source、Delegate  value）は、バリューパラメータにより与えられるデリゲートファイナルオカレンス（あれば）を、ソースパラメータにより与えられるデリゲートの呼び出しリストから取り除くことにより形成される呼び出しリストを備えたデリゲートを戻す。呼び出しリストから取り除かれるデリゲートは、デリゲートを問い合わせ中の呼び出しリストメンバーとして式value．Equals（delegate）が真となるファイナルデリゲートである。バリューパラメータがヌルである場合、又はバリューパラメータにより与えられるデリゲートがソースの呼び出しリストに出現しない場合、結果はソースパラメータである。結果としての呼び出しリストが空である場合、結果はヌルである。ソールパラメータがヌルである場合、結果はヌルである。
【００７８】
式public  final  Object  dynamicInvoke（Object〔〕arg）は、レイトバインド方式（Delegate. dynamicInvoke）でメソッドを呼び出すのに用いることができる。呼び出されると、dynamicInvokeメンバーは、arg引き数の要素を引き数としてメソッドへ送って、デリゲートをカプセル化するメソッドを実行する。DynamicInvokeの結果が、カプセル化されたメソッドの呼び出しの結果である。メソッド呼び出しの結果がオブジェクトリファレンスであれば、このリファレンスが戻される。そうではなく、結果がプリミティブ値であれば、このプリミティブ値がオブジェクトに包まれて戻される。（例えば、ブール値はブールオブジェクトに包まれる。）そうでなければ、メソッドのリターンタイプはボイドであり、ｎｕｌｌ値を含むオブジェクトが戻される。
【００７９】
public  final  static  Method  getMethod（）メソッドは、リファレンスを（ターゲット、メソッド）対のメソッドである独自のメソッドオブジェクトに戻す。
【００８０】
public  final  static  Object  getMethod（）メソッドは、リファレンスを呼び出し可能なエンティティをカプセル化するのに必要な（インスタンス、メソッド）組のインスタンス部分に戻す。
【００８１】
ｐｕｂｌｉｃ  Ｄｅｌｅｇａｔｅ〔〕ｇｅｔＩｎｖｏｃａｔｉｏｎＬｉｓｔ（）メソッドは、このデリゲートの呼び出しリストを呼び出し順に戻す。マルチキャストでないデリゲートに対しては、結果は常に単一要素を有するアレイである。マルチキャストデリゲートに関しては、以下に述べるように、結果アレイは２つ以上の構成要素を有する。戻されたアレイ内の各要素の呼び出しリストは、正確に１つのエントリを有することが保証されている。
【００８２】
（マルチキャストデリゲート）
すべてのマルチキャストデリゲートはクラスＭｕｌｔｉｃａｓｔＤｅｌｅｇａｔｅから出ており、Ｊａｖａの本実施例では、Class com．ms. lang. Multicast Delegateとして言及されている。マルチキャストデリゲートの呼び出しには、複数のメソッドが呼び出される効果がある。デリゲートのｉｎｖｏｋｅにより呼び出されるメソッドのセットは、デリゲートの呼び出しリストとして言及され、ｇｅｔＩｎｖｏｃａｔｉｏｎＬｉｓｔメソッドを使って入手可能である。
【００８３】
Ｄｅｌｅｇａｔｅから直接継承するデリゲートは、１つの要素、即ち自身を含む呼び出しリストを常に有する。ＭｕｌｔｉｃａｓｔＤｅｌｅｇａｔｅクラスから継承するデリゲートは、２つ以上の構成要素を含む呼び出しリストを有する。メソッドＤｅｌｅｇａｔｅ．ｃｏｍｂｉｎｅ及びＤｅｌｅｇａｔｅ．ｒｅｍｏｖｅメソッドは新しい呼び出しリストを作成するのに用いられる。
【００８４】
ｉｎｖｏｋｅメソッド及びｄｙｎａｍｉｃＩｎｖｏｋｅメソッドは、送られてくる引き数を使って呼び出しリスト内の各デリゲートを呼び出すことにより、マルチキャストする。デリゲートは、呼び出しリスト内に出現する順番で、同期的に呼び出される。デリゲートの１つが例外を戻せば、マルチキャストは停止し、例外が呼び出しメソッドの呼び出し人に伝播される。マルチキャスト呼び出しが行われている間に、Ｄｅｌｅｇａｔｅ．ｃｏｍｂｉｎｅ及びＤｅｌｅｇａｔｅ．ｒｅｍｏｖｅへの呼び出しが起こるかもしれない。そのような呼び出しは、既に進行中のマルチキャストに採用されている呼び出しリストに影響しない。
【００８５】
本発明の本実施例では、クラスMulticastDelegate（４０）は、図７に示すように定義される。
【００８６】
式protected  MulticastDelegate  nextは、マルチキャストチェーン内の次のデリゲートへの内部リファレンスである。正しい呼び出し順序が保存されるためには「次」のデリゲートを、このデリゲートがカプセル化するメソッドを呼び出す前に呼び出さなければならない。
【００８７】
protected MulticastDelegate（Object  target、String  methodName）コンストラクタは、デリゲートベースクラス内で定義された対応するコンストラクタのように機能する。
【００８８】
マルチキャストデリゲートを呼び出す別の実施態様は、デリゲートのアレイを構築し、マルチキャストデリゲートの「次」のチェーンを歩いて調べることにより呼び出すことである。このリストは、プログラムのスタックに配置することができる。次にバーチャルマシンインタプリタソフトウェア１６は、このアレイを逆の順序に歩いて、マルチキャストデリゲートの呼び出しメソッドへ送られてくるパラメータを使って各デリゲートの呼び出しメソッドを呼び出す。この技法の利点は、スタックにはマルチキャストデリゲートの呼び出しメソッドへ送られてくるパラメータの、最大でも２つのコピーしかないので、プログラムのスタックはそれほど深くなくてよいことである。
【００８９】
（別の実施例：スタティックメンバーのラッピング）
本発明のある別の実施例では、Ｊ＋＋言語が更に拡張され、クラス上のラップスタティックメンバーを包含している。この目的のために、形状がデリゲートベースクラスにより定義されている「クラス」コンストラクタが提供されている。このコンストラクタに対する引き数、クラス及びストリングメソッドの名前は、デリゲートのタイプと組み合わせられ、デリゲート定義に一致する指示されたクラス上のスタティックメンバーを独自に特定する。新たに構築されるデリゲートは、このスタティックメソッドをカプセル化する。このコンストラクタは、
protected  Delegate（Class  class、StringmethodName）
の形態を取る。
【００９０】
このコンストラクタは、新しく作成されるデリゲートオブジェクトが引き数により特定されるスタティックメソッドをカプセル化するように、この新しく作成されるデリゲートオブジェクトを初期化する。クラスがヌルである場合、ＮｕｌｌＰｏｉｎｔＥｘｃｅｐｔｉｏｎ例外が浮上する。MethodName引き数は、先に定義されたように、一致しており、アクセス可能で、且つ適切なメソッドを告げなければならない。一致するターゲットメソッドが見つからない場合は、実行時にＩｌｌｅｇａｌＡｒｇｕｍｅｎｔＥｘｃｅｐｔｉｏｎ例外が投入される。そのようなメソッドが見付からない場合は、ＩｌｌｅｇａｌＡｒｇｕｍｅｎｔＥｘｃｅｐｔｉｏｎが投入される。
【００９１】
デリゲートがスタティックメンバーをラッピングするコンパイル時の第一段階では、検索するクラス又はインターフェースが決定されなければならない。それがTypeName．Identifierの形態を取る修飾された名前である場合、メソッドの名前はIdentifierであり、検索するクラスはTypeNameと名付けられたクラスである。TypeNameがクラスではなくインターフェースの名前である場合、この形態はスタティックメソッドだけを指名することができて、インターフェースはスタティックメソッドを持っていないので、コンパイル時エラーが生じる。クラスのインスタンスメンバーをラッピングするケースと同じく、メソッドが適切かどうか決定することも必要である。デリゲートインスタンス生成式に対し、一致していて、アクセス可能なメソッド宣言がある場合、それはそのデリゲートインスタンス生成式に対するコンパイル時宣言と呼ばれる。
【００９２】
更にコンパイル時宣言には別のチェックがなされなければならない。メソッド指示子が識別子の形のMethodNameを有し、メソッド指示子がスタティックメソッド、スタティックイニシャライザ又はスタティック変数のイニシャライザ内に現れる場合、コンパイル時エラーが生じる。別の点で、スタティックメンバーのラッピングは、上記のように、インスタンスメンバーのラッピングへの拡張又は変更である。
【００９３】
この別の実施例によれば、更に対応コンストラクタが、マルチキャストデリゲートクラス：protected  MulticastDelegate（Class  class、String  methodName）に提供されている。このコンストラクタは、デリゲートベースクラス内で定義される対応コンストラクタのように機能する。
【００９４】
（交互に呼び出し可能なインターフェース）
マイクロソフト（登録商標）ビジュアルＪ＋＋は、多重継承(multiple-inheritance)をサポートしない。しかしときには、そのようなインターフェースが、現存するコードをデリゲートタイプのスタイルに変換するために必要となることもあるであろう。この状況は、java.lang.  Thread vs.java.lang.Runnableに似ているかもしれない。この問題に取り組むために、本発明の一つの実施例は、図８に示されているように、マイクロソフト（登録商標）ビジュアルＪ＋＋を拡張してcom.ms.lang.Callableインターフェース４２を含むようにする。デリゲートはこのインターフェースを実行するのが望ましい。
【００９５】
（デリゲートベースのイベントモデル）
オブジェクト指向プログラミングでは、イベントは、イベントソースが一人のイベントリスナー（又はイベントリスナーのセット）に匿名で、数種類の状態遷移が発生したことを通知できる構成である。一般的にイベントは、構成要素が構成要素を用いている機能性コードを如何に公開するかについて説明する「構成要素モデル」と呼ばれる大規模システム内で用いられる。最新のほとんどの構成要素モデルは、構成要素がその（構成要素の状態を説明する）特性、その（構成要素が実行できるアクションを示す）メソッド及びその（関心事が生じた構成要素からの通知である）イベントについてどのように公開するかを基本レベルで説明する。
【００９６】
イベント呼び出しは、逆のメソッド呼び出しに似ている。メソッドを呼び出すために、構成要素消費者は、複数の引き数を送って構成要素上のメソッドを呼び出す。イベントについては、呼び出しが反対方向であり、構成要素が複数の引き数を送って、構成要素消費者により提供されるメソッドを呼び出す。呼び出しの方向の違いに加えて、他にも幾つか顕著な違いが見られる。
【００９７】
メソッド呼び出しに関しては、消費者は通常、呼び出されている構成要素に明示的に従属している。これに対し、イベント呼び出しは通常匿名であり、構成要素は構成要素消費者に明示的には従属しない。代わりに、リスナーは、イベントソースにより提供されるメカニズムを使ってイベント又はイベントセットに接続できる。
【００９８】
更にメソッド呼び出しに関しては、被呼び出し人は、メソッドの形状、すなわち数とタイプ、又は引き数とリターンタイプを決定する。イベント呼び出しに関しては、イベントソース（呼び出し人）は形状を決定する。
【００９９】
以下に述べる本発明によるデリゲートベース構成要素モデルの実施例では、イベントは、通常、構成要素（販売者により書き込まれることが多い）とイベントハンドリングコード（構成要素を使って開発者により書き込まれる）との間の交信に用いられる。以下に説明されている構成要素モデルの実施例は、シングルキャスト及びマルチキャスト両方のイベントを支援する。
【０１００】
（クラス及びインターフェース）
以下に、本発明の実施例により、どのようにイベントを出現させ、利用するかを述べる。ここでは、幾つかのクラスが定義され、論じられている。
１）クラスEvent。イベントは、イベントオブジェクト内の関心のある状態をパッケージする。そのようなイベントオブジェクトは全てイベントクラスから出ている。イベントクラスはパラメータなしのイベントにも直接用いられる。
２）デリゲートEventHandler、これはクラスイベントと協力して用いられる。
３）クラスCancelEvent、これはキャンセルすることのできるアクションに用いられる。イベントソースは、アクションがすぐに発生することを、アクションが起こる前に関心あるリスナーに通知する。各リスナーはアクションを「キャンセル」する機会を有する。
４）デリゲートCancelEventHandler、これはクラスキャンセルイベントと協力して用いられる。
【０１０１】
（イベントの立上げ）
イベントを立ち上げるためには、イベントソースは、次の内の一つ又はそれ以上を行う。
１）イベントクラスを定義する
２）「イベントハンドラ」デリゲートを定義する
３）イベントソースがイベントと接続し、その後それと切断することができるようにする「追加」及び「取り外し」メソッドを提供するか、又は
４）を立ち上げる「イベント立上げ」メソッドを提供する。
【０１０２】
（イベントクラスの定義）
これは、クラスイベントから出て追加の文脈上の情報を潜在的に追加する。現存するイベントクラスを採用することができるので、新しいイベントクラスを定義することは必ずしも必要ではない。
【０１０３】
イヴベントクラスは約束によって用いられる。イベントクラスをまったく採用しないイベントを定義して用いることは可能である。本例の構成要素モデルは、イベントワイヤリングシナリオ及びバージョニングを容易にするために、オブジェクトとしてイベントをパッケージすることを勧める。これらのテーマについては、更に以下で論じる。ウインドウクラスにより持ち上げられたマウスイベントに対しては、図９に示されているイベントクラスを定義することができる。
【０１０４】
（「イベントハンドラ」デリゲートの定義）
このような１つのデリゲートが、イベントの各関心事セットに必要である。そのようなデリゲートは、多数のイベントに用いられる。約束により、イベントハンドラデリゲートは、
public multicast delegate  void  ＜Name＞Handler（Object  source、＜EventType  e）
のパターンと一致するように定義されている。
【０１０５】
図９のマウスイベント例４４では、これが
public multicast delegate void
MouseEventHandler（Object  source、MouseEvent  e）
を意味する。
【０１０６】
ここに設定されているイベントハンドリングモデルの実施例は、イベントソースがイベントに接続し、その後イベントを切断できるような「追加」及び「取り外し」メソッドを提供する。約束により、イベントハンドラデリゲートは、
Public  void
addOn＜EventName＞Handler（＜EventHandlerType＞handler）
Public  void
removeOn＜EventName＞Handler（＜EventHandlerType＞handler）
のパターンに一致するように定義される。
【０１０７】
マウスイベント例に対しては、これは
Public void addOnMouseMoveHandler（MouseEventHandlerhandler）
Public  void  removeOnMouseMoveHandler（MouseEventHandlerhandler）
を意味する。
【０１０８】
（イベントを立ち上げる「イベント立上げ」メソッドの提供）
このメソッドは、引き出されたクラスが、イベントを立上げ、ベースクラス内に立ち上げられたイベントをキャンセルし、構成要素の消費者から妨害されずに前後処理できるようにするメソッドである。メソッド本体は、引き数を送り、ｔｈｉｓをイベントに対するソースパラメータの値として加えて、適切なデリゲート値付きの特性上にＤｅｌｅｇａｔｅ．ｉｎｖｏｋｅを呼び出すイベントを立ち上げる。ファイナルクラスに対しては、引き出されるクラスが存在することは有り得ないので、そのようなメソッドを提供する必要はない。約束により、イベントハンドラデリゲートはパターン
protected void on＜EventName＞（＜EventType＞ e）
に一致するように定義される。
【０１０９】
マウスイベント例に対して、図１０に示すメソッドが示されている。
【０１１０】
（イベントのハンドリング）
イベントを聴くために、イベントリスナーは次のことを行う。
１）ＪＬＳに説明されている、クラス構成要素マネジャーを使って、どのイベントが構成要素に利用可能かを学習する。
２）例えば図１１のコード４８で示されているように、応答イベント特性に対して用いられるデリゲートにより定義される正当なシグネチャを使って、イベントハンドラ関数を作成する。
３）例えば図１２のコード５０で示されているように、イベントソースにより提供される「追加」メソッドを呼び出すことにより、イベントハンドリングコードをイベントに接続する。
４）例えば図１３のコード５２で示されているように、ソースにより提供される「取り外し」メソッドを呼び出すことにより、イベントハンドリングコードをイベントから、随意的に、切断する。ほとんどの場合、明示的に切断する必要はない。
【０１１１】
（Ｊ＋＋Ｃｏｄｅでのイベントモデルの第一例、ボックス例）
図１４Ａ―１４Ｂは、上記デリゲート及びイベントモデルの適用を示す例Ｊ＋＋コード５４の例である。図１４Ａ―１４Ｂでは、マウスイベントクラス及びマウスイベントハンドラデリゲートが宣言されている。２つのボックスインスタンスを用いる構成要素消費者の例と、ボックスクラス宣言とが述べられている。
【０１１２】
（Ｊ＋＋Ｃｏｄｅでのイベントモデルの別例、スマイリー例）
パラメータが無しのイベントが立ち上げられる簡単なイベント例が、図１５Ａ―１５Ｂに示されている。図１５Ａ―１５ＢのＪ＋＋プログラム５６で、そのハッピー特性が変わるときに、スマイリー制御がイベントを立ち上げる。
【０１１３】
（シングルキャストイベント及びマルチキャストイベント）
上記イベントモデルは、シングルキャストシナリオにもマルチキャストシナリオにも等しく上手く作用する。ここに述べられている実施例では、好適な約束により、全イベントはマルチキャストである。しかし、シングルキャストイベントを定義することは実に簡単であり、デリゲート宣言内のマルチキャスト変更子を省略するだけである。イベントは、クラス定義又はインターフェースのどちらかに現れる。一組のイベントを１つのインターフェース内に定義することと、このインターフェースを支援する複数のクラスを有することとが可能である。
【０１１４】
マルチキャストイベントモデルとシングルキャストイベントモデルとの間の基本的な違いは、どのように接続がなされるかである。マルチキャストの場合、マルチキャストデリゲートを用いて「addOn」及び「removeOn」メソッドを採用することが必要である。シングルキャストでは、非マルチキャストデリゲートを用いて、特性設定及び入手によりイベントとの接続／切断がなされるようにすることができる。つまり構成要素は、出現する各イベントに対するデリゲート値付き特性を提供する。例えばMouseMoveイベントでは、図１６のコード５８で示されているように、「foo」イベントを出現させようとする構成要素は、「OnFoo」特性を出現させることになる。
【０１１５】
（クラスイベント）
クラスイベントは以下の複数の目的に寄与する：
１）クラスイベントは、全イベントに対しベースクラスとして作用する。約束により、構成要素に対するイベントは、タイプがクラスイベントから出るクラスであるような単一のパラメータを採用する。
【０１１６】
２）クラスイベントは、状態を持っていないイベントに用いられる。一般的にスタティックメンバーＥＭＰＴＹは、図１７に示されているコード６０にインスタンス生成されているように、この目的に用いられ、イベントが効果的に立ち上げられることができるようにする。
【０１１７】
（デリゲートイベントハンドラ）
デリゲートイベントハンドラは、図１８のコード６２に示されているように、タイプイベントの単一のパラメータを取るイベントに用いられる。
【０１１８】
（クラスキャンセルイベント）
キャンセルイベントクラスは、キャンセルすることができるアクションを参照するイベントに用いられる。キャンセルイベントクラスは、当該アクションがキャンセルされているかどうかを述べるｃａｎｃｅｌという名のブールフィールドを提供する。真の値は、アクションがキャンセルされていることを示し、偽の値は、アクションがキャンセルされていないことを示す。ｃａｎｃｅｌに対する最初の値は、提供されるコンストラクタを使って提供される。一般的に、ｃａｎｃｅｌはｆａｌｓｅに初期化され、そのためイベントが処理されないか又はイベントハンドラがｃａｎｃｅｌフィールドを変更しなければ、イベントソースは、アクションを実行するパーミッションが与えられているとみなす。キャンセルイベントクラスは、図１９のコード６４に示されている。
【０１１９】
（デリゲートキャンセルイベントハンドラ）
デリゲートキャンセルイベントハンドラは、図２０のコード６６に示されているように、タイプキャンセルイベントの単一のパラメータを取るイベントに用いられる。
【０１２０】
（デリゲートに関する他の利用）
既に示されているように、デリゲートは全般に、特にイベント関係のシナリオに役立つ。しかし、Ｊ／直接呼び出し及びレイジー呼び出しにおけるコールバック機構に取って替わるような非イベント指向シナリオにも有益である。
【０１２１】
（他のプログラム言語及びシステムへの本発明の適用／代替実施例）
本明細書に記載の本発明のデリゲート及びイベントモデルの実施例は、拡張マイクロソフト（登録商標）ビジュアルＪ＋＋として示されている。しかし、本明細書に記述されている本発明は、Ｃ＋＋及びマイクロソフト（登録商標）ビジュアルベーシックのようなオブジェクトベースのプログラミング言語のような他のオブジェクト指向プログラミング言語システムに、又はマイクロソフト社又は他の開発者から入手可能なＪ＋＋の他のバージョンに広く適用されることは理解頂けるであろう。
【０１２２】
更に、本明細書に記述されている本発明は、本発明の発明的コードを使って書かれるコンピュータープログラムと、コンピュータープログラムをコンピューターシステムで実行できるコマンドへ翻訳するコンパイラ、実行時バーチャルマシン及び他のプログラミングシステムとの両方に適用可能であり、その両方の形式を取る。
【０１２３】
本発明は更に、これに限定されるわけではないが、ハードドライブ、フレキシブルディスク、コンピューターメモリ、又はコードを１つのコンピューター又は記憶媒体から他のコンピューター又は記憶媒体へ転送するのに用いられる電気信号のような、担体の中又は上において、デリゲート及びイベントモデルを物理的なコンピューターコードフォームに具体化する。
【０１２４】
更に、本明細書に開示されている実施例はソフトウェアで実施されているが、ここに記述されている本発明はソフトウェアでの実行だけに決して限定されるものではないし、フィルムウェア及びシリコンベース又は他の形態のハードワイヤードロジック、あるいはハードワイヤードロジック、フィルムウェア、ソフトウェア又は何らかの好適な代用品の組み合わせ内でのインプリメンテーションをも考慮していることは明らかである。
【０１２５】
（結論）
このように、オブジェクト指向又はオブジェクトベースのプログラミングシステムにおいてメソッドへのリファランスをカプセル化し、そのリファレンスが安全であることを保証するためのメソッド及び装置を説明してきた。上に述べたように、本発明は、
ａ）参照されるメソッドの形状を定義するエンティティを定義し、
ｂ）メソッドへのリファレンスを入手し、
ｃ）このリファレンスを任意のデータ構成で保存し、
ｄ）リファレンスを他のパーティにより書き込まれたコードへ送り、
ｅ）メソッドリファレンス保持者誰にでもメソッド呼び出しができるようにし、
ｆ）メソッドリファレンス保持者がターゲットオブジェクト及び参照されるメソッドを決定できるようにする。
【０１２６】
更に、本発明のプログラミングシステムは、
ａ）開発者が遅い時期（実行時）ではなく早く（コンパイル時）タイプ不適合問題を学習でき、
ｂ）開発ツールが、開発者に、デリゲートを用いる構成要素の形状について情報を提示することができる
ようにしながら、強く型付けされた方式で上記目的を達成する。
【０１２７】
更に、本発明は、イベント関係のコードがデリゲート内にカプセル化され得るイベントベースプログラミングを提供する。
【図面の簡単な説明】
【図１】  本発明の主な構成要素のブロック図である。
【図２】  本発明に適用可能なプラットフォーム及び担体である。
【図３】  本発明によるJ＋＋コンピュータープログラム例である。
【図４】  本発明によるアーリーバインドデリゲートの宣言例である。
【図５Ａ】  本発明によるアーリーバインドデリゲートの宣言例である。
【図５Ｂ】  ストリングメソッド名前に基づきレイトバインドデリゲートを構築する例である。
【図６】  本発明によるクラスデリゲートの定義例である。
【図７】  クラスマルチキャストデリゲートの定義例である。
【図８】  マイクロソフト（登録商標）ビジュアルJ＋＋を拡張してｃｏｍ．ｍｓ．ｌａｎｇ．Callableインターフェースを含むようにする実施例である。
【図９】  本発明によるイベントクラスの例である。
【図１０】  本発明によるイベント処理コードの例である。
【図１１】  本発明によるイベント処理コードの例である。
【図１２】  本発明によるイベント処理コードの例である。
【図１３】  本発明によるイベント処理コードの例である。
【図１４Ａ】  本発明による、デリゲートを用いるイベント処理プログラムの例である。
【図１４Ｂ】  本発明による、デリゲートを用いるイベント処理プログラムの例である。
【図１５Ａ】  本発明によるイベント処理プログラムの例である。
【図１５Ｂ】  本発明によるイベント処理プログラムの例である。
【図１６】  本発明による、シングルキャストのイベント処理プログラムの例である。
【図１７】  本発明によるクラスイベントの定義である。
【図１８】  本発明による、イベントハンドラ宣言の定義例である。
【図１９】  本発明による、キャンセルイベントクラスの定義例である。
【図２０】  本発明による、イベントハンドラの宣言である。
【図１】
0004220127.tif 000002
【図２】
0004220127.tif 000003
【図３】
0004220127.tif 000004
【図４】
0004220127.tif 000005
【図５Ａ】
0004220127.tif 000006
【図５Ｂ】
0004220127.tif 000007
【図６】
0004220127.tif 000008
【図７】
0004220127.tif 000009
【図８】
0004220127.tif 000010
【図９】
0004220127.tif 000011
【図１０】
0004220127.tif 000012
【図１１】
0004220127.tif 000013
【図１２】
0004220127.tif 000014
【図１３】
0004220127.tif 000015
【図１４Ａ】
0004220127.tif 000016
【図１４Ｂ】
0004220127.tif 000017
【図１５Ａ】
0004220127.tif 000018
【図１５Ｂ】
0004220127.tif 000019
【図１６】
0004220127.tif 000020
【図１７】
0004220127.tif 000021
【図１８】
0004220127.tif 000022
【図１９】
0004220127.tif 000023
【図２０】
0004220127.tif 000024