Skip to main content

This is documentation for Caché & Ensemble. See the InterSystems IRIS version of this content.Opens in a new tab

For information on migrating to InterSystems IRISOpens in a new tab, see Why Migrate to InterSystems IRIS?

動的ディスパッチの実装

この章では、Caché クラスの動的ディスパッチについて説明します。この章は、以下のトピックで構成されています。

このドキュメントをオンラインで表示している場合は、このドキュメントの "序文" を使用すると、他のトピックをすばやく見つけることができます。

動的ディスパッチの概要

Caché クラスには、動的ディスパッチに対するサポートを含めることができます。動的ディスパッチが使用中で、プログラムがクラス定義の一部でないプロパティまたはメソッドを参照している場合、ディスパッチ・メソッドと呼ばれるメソッドが呼び出され、未定義メソッドまたは未定義プロパティを解決しようと試みます。例えば動的ディスパッチを使用すると、定義されていないプロパティ値を返したり、実装されていないメソッドのためにメソッドを呼び出すことができます。ディスパッチ先はクラス記述子に表示されないという点で動的であり、実行時まで解決されません。

Caché は、実装可能なディスパッチ・メソッドを多数作成します。各メソッドは、さまざまな状況で見つからない要素を解決しようと試みます。

ディスパッチ・メソッドを実装すると、次のような効果があります。

  • アプリケーションの実行時、コンパイル済みクラスの一部でない要素が見つかると、ディスパッチ・メソッドを呼び出してその要素を解決しようと試みます。

  • この解決には、そのクラスを使用中のアプリケーション・コードは使用されません。 Caché が自動的にディスパッチ・メソッドの存在をチェックし、メソッドが存在すればそのディスパッチ・メソッドを呼び出します。

動的ディスパッチを実装するメソッドのコンテンツ

アプリケーション開発者は、ディスパッチ・メソッドのコンテンツを制御することができます。そのクラスが解決しようと試みるメソッドまたはプロパティを実装するのに必要なものを、ディスパッチ・メソッドのコンテンツ内のコードに指定できます。

動的ディスパッチのコードには、同一エクステント、同一パッケージ、同一データベース、同一ファイルシステムや、その他のあらゆる基準からメソッドを特定するような処理を含めることができます。ディスパッチ・メソッドが一般的なケースを提供する場合は、この一般的な解決が含まれる継続した処理が記録されるように、メソッドでこの操作を記録するログも作成することをお勧めします。

例えば次のような %DispatchClassMethod() を実装すると、アプリケーション・ユーザがどのような操作を行う際にもメソッドを呼び出せるようになります。

ClassMethod %DispatchClassMethod(Class As %String, Method As %String, args...)
{
    WRITE "The application has attempted to invoke the following method: ",!,!
    WRITE Class,".",Method,!,!
    WRITE "This method does not exist.",!
    WRITE "Enter the name of the class and method to call",!
    WRITE "or press Enter for both to exit the application.",!,!


    READ "Class name (in the form 'Package.Class'): ",ClassName,!
    READ "Method name: ",MethodName,!
    
    IF ClassName = "" && MethodName = "" {
        // return a null string to the caller if a return value is expected
        QUIT:$QUIT "" QUIT
    } ELSE {
        // checking $QUIT ensures that a value is returned 
        // if and only if it is expected
        IF $QUIT {
            QUIT $CLASSMETHOD(ClassName, MethodName, args...)
        } ELSE {
            DO $CLASSMETHOD(ClassName, MethodName, args...)
            QUIT
        }
    }
}

アプリケーションの全クラスのセカンダリ・スーパークラスであるクラスにこのメソッドを含めておくと、存在しないクラス・メソッドに対してアプリケーション全体の呼び出し処理を構築できます。

返り値

どのディスパッチ・メソッドにも、指定の返り値はありません。これは、各ディスパッチ・メソッドは、最初にディスパッチの必要性が生じた呼び出しと同じタイプの出力を提供する必要があるためです。

ディスパッチ・メソッドがメソッドまたはプロパティを解決できない場合は、$SYSTEM.Process.ThrowError() を使用して <METHOD DOES NOT EXIST> エラーまたは <PROPERTY DOES NOT EXIST> エラーなどを返すことができます。

動的ディスパッチ・メソッド

不明メソッドと不明プロパティを解決するのに実装できるメソッドは、次のとおりです。

%DispatchMethod()

このメソッドは、不明なメソッド呼び出しを実装します。構文は、以下のとおりです。

Method %DispatchMethod(Method As %String, Args...)

ここで、最初の引数は参照メソッド名を指し、次の引数は元のメソッドに渡される全引数を保持した配列を指します。引数の数とそのタイプは解決対象となるメソッドによって異なるため、%DispatchMethod() 内のコードで正しく処理する必要があります (クラス・コンパイラでは、タイプに関する想定がまったくできません)。Args... 構文でこれを柔軟に処理することができます。

%DispatchMethod() は、そのクラスに関連付けられている不明なインスタンス・メソッドを解決しようと試みますが、返り値が指定されていないため、解決できた場合は、呼び出し元が返り値を予期するかどうかにかかわらず、解決対象のメソッドによって決定されたタイプの値が返されます。

%DispatchMethod() を使用すると、不明な多次元プロパティ参照も解決できます。つまり、プロパティの値も取得できます。ただし、多次元プロパティ参照は動的ディスパッチでのみサポートされています。$DATA, $ORDER、および $QUERY はサポートされていません。また、変数リストを用いる SET コマンドもサポートされていません。

%DispatchClassMethod()

このメソッドは、不明なクラス・メソッド呼び出しを実装します。構文は、以下のとおりです。

ClassMethod %DispatchClassMethod(Class As %String, Method As %String, Args...)

最初の 2 つの引数は参照クラス名と参照メソッド名を指します。3 番目の引数は、元のメソッドに渡される引数全体を保持する配列を指します。引数の数とそのタイプは解決対象となるメソッドによって異なるため、%DispatchClassMethod() 内のコードで正しく処理する必要があります (クラス・コンパイラでは、タイプに関する想定がまったくできません)。Args... 構文でこれを柔軟に処理することができます。

%DispatchClassMethod() は、そのクラスに関連付けられている不明なインスタンス・メソッドを解決しようと試みますが、返り値が指定されていないため、解決できた場合は、呼び出し元が返り値を予期するかどうかにかかわらず、解決対象のメソッドによって決定されたタイプの値が返されます。

%DispatchGetProperty()

このメソッドは、不明プロパティの値を取得します。構文は、以下のとおりです。

Method %DispatchGetProperty(Property As %String)

ここで、引数は参照されるプロパティを指します。%DispatchGetProperty() は、そのクラスに関連付けられている不明なインスタンス・メソッドを解決しようと試みますが、返り値が指定されていないため、解決できた場合は、解決対象のプロパティ・タイプの値が返されます。

%DispatchSetProperty()

このメソッドは、不明プロパティの値を設定します。構文は、以下のとおりです。

Method %DispatchSetProperty(Property As %String, Value)

この引数には、参照先のプロパティ名とそのプロパティに設定する値を指定します。

%DispatchSetMultidimProperty()

このメソッドは、不明な多次元プロパティの値を設定します。構文は、以下のとおりです。

Method %DispatchSetMultidimProperty(Property As %String, Value, Subs...)

最初の 2 つの引数には、参照先のプロパティ名とそのプロパティに設定する値を指定します。3 番目の引数 Subs は、添え字の値を含む配列を指します。 Subs には添え字の数を指定する整数値が、Subs(1) には最初の添え字の値が、Subs(2) には 2 番目の添え字の値が入り、以下同様に続きます。添え字を指定しないと、Subs が未定義になります。

多次元プロパティ参照は、動的ディスパッチでのみサポートされています。$DATA, $ORDER、および $QUERY はサポートされていません。また、変数リストを用いる SET コマンドもサポートされていません。

Note:

%DispatchGetMultidimProperty() ディスパッチ・メソッドはないことに注意してください。 これは、多次元プロパティ参照がメソッド呼び出しと同じためです。 したがって、この種の参照は %DispatchMethod() を呼び出すため、メソッド名と多次元プロパティ名を区別するためのコードを含めておく必要があります。

FeedbackOpens in a new tab