Caché クラス
特にオブジェクト・クラスに注目する前に、一般的にクラスを操作および作成するための基本的な規則について見直しておくと役立ちます。したがって、この章では、Caché でクラスを定義および操作するための基本的な規則について説明します。以下のトピックについて説明します。
次の章では、オブジェクトとオブジェクト・クラスについて説明します。ネームスペースについては、このドキュメント内で後で説明します。
クラス名とパッケージ
各 Caché クラスは名前を持ち、その名前は、それが定義されているネームスペース内で一意である必要があります。完全なクラス名は、例えば、package.subpackage.subpackage.class のような、1 つ以上のピリオドで区切られた文字列です。短いクラス名は、この文字列内の最後のピリオドの後の部分であり、最後のピリオドの前の部分はパッケージ名です。
パッケージ名は単なる文字列ですが、ピリオドが含まれている場合、Caché 開発ツールは、ピリオドで区切られた各部分をサブパッケージとして処理します。スタジオおよびその他のツールでは、便宜上、これらのサブパッケージはフォルダの階層として表示されます。例えば、スタジオの [ワークスペース] ウィンドウの [ネームスペース] タブでは、パッケージは以下のように表示されます。
スタジオの [ワークスペース] ウィンドウの [プロジェクト] タブには、現在選択されているスタジオ・プロジェクトの内容が表示されます。プロジェクトにパッケージ全体またはサブパッケージが含まれている場合、このタブのパッケージ・アイコンは、青い斜線の入ったフォルダになります。パッケージの一部のクラスのみがプロジェクトに含まれている場合は、通常のアイコンが使用されます。以下に例を示します。
このドキュメントでは、プロジェクトについて詳細には説明しません。詳細は、"スタジオの使用法" を参照してください。
スタジオには、個別のクラス、パッケージ全体、およびプロジェクトを XML ファイルにエクスポートするオプションと、これらの項目を XML ファイルからインポートするオプションがあります。
クラス定義の基本的なコンテンツ
Caché クラスの定義には、以下の項目を含めることができ、これらはすべてクラス・メンバと呼ばれます。
-
パラメータ — パラメータは、このクラスによって使用される定数値を定義します。この値はコンパイル時に設定されます。
-
メソッド — インスタンス・メソッドとクラス・メソッド (他の言語では静的メソッドと呼ぶ) の 2 種類のメソッドがあります。多くの場合、メソッドはサブルーチンです。
-
プロパティ — プロパティには、クラスのインスタンスのデータが格納されます。
-
クラス・クエリ — クラス・クエリは、クラスが使用できる SQL クエリを定義し、クエリのためのコンテナとして使用するクラスを指定します。
-
XData ブロック — XData ブロックは、クラスによって使用される、クラス内の整形式 XML ドキュメントです。
これらには、多数の用途があります。
-
永続クラスにのみ関連する、他の種類のクラス・メンバについては、次の章で説明します。
クラス定義には、キーワードを含めることができ、それらはクラス・コンパイラ動作に作用します。キーワードには、クラス全体に対して指定できるものと、特定のクラス・メンバに対して定義できるものがあります。これらのキーワードは、クラス・コンパイラが生成するコードに作用し、その結果、クラスの動作を制御します。
以下に、簡単な Caché クラス定義を示します。
Class MyApp.Main.SampleClass Extends %RegisteredObject
{
Parameter CONSTANTMESSAGE [Internal] = "Hello world!" ;
Property VariableMessage As %String [ InitialExpression = "How are you?"];
Property MessageCount As %Numeric [Required];
ClassMethod HelloWorld() As %String
{
Set x=..#CONSTANTMESSAGE
Quit x
}
Method WriteIt() [ ServerOnly = 1]
{
Set count=..MessageCount
For i=1:1:count {
Write !,..#CONSTANTMESSAGE," ",..VariableMessage
}
}
}
以下の点に注意してください。
-
最初の行は、クラスの名前を指定します。MyApp.Main.SampleClass は完全なクラス名であり、MyApp.Main がパッケージ名、SampleClass が短いクラス名です。
スタジオおよび他のユーザ・インタフェースでは、各パッケージはフォルダとして処理されます。以下はその例です。
-
クラス名は、編集できません(変更した場合、変更は無視され、次にクラス定義を開いたときは元のクラス名が表示されます)。クラス名の変更の詳細は、このドキュメントで後述する “クラス名の変更” を参照してください。
-
Extends はコンパイラ・キーワードです。
Extends キーワードは、このクラスが %RegisteredObjectOpens in a new tab のスーパークラスであることを指定します。これはシステム・クラスであり、次の章で説明します。このクラスは、1 つのクラスのみを拡張しますが、複数の他のクラスを拡張することもできます。また、それらのクラスが他のクラスを拡張することもできます。
-
CONSTANTMESSAGE はパラメータです。慣例で、Caché システム・クラスのすべてのパラメータの名前はすべて大文字にします。これは、便利な慣例ですが、これに従う必要はありません。
Internal キーワードはコンパイラ・キーワードです。これは、このパラメータが内部であることを示し、クラス・ドキュメントで表示されないようにします。このパラメータは文字列値を持ちます。
-
VariableMessage および MessageCount はプロパティです。As の後の項目は、これらのプロパティのタイプを示します。InitialExpression および Required はコンパイラ・キーワードです。
-
HelloWorld() はクラス・メソッドであり、文字列を返します。これは As の後の項目によって示されます。
このメソッドは、クラス・パラメータの値を使用します。
-
WriteIt() はインスタンス・メソッドであり、値を返しません。
このメソッドは、クラス・パラメータの値と 2 つのプロパティの値を使用します。
ServerOnly コンパイラ・キーワードは、このメソッドが Java または C++ クライアントに投影されないことを意味します。
以下のターミナル・セッションは、このクラスの使用法を示しています。
SAMPLES>write ##class(MyApp.Main.SampleClass).HelloWorld()
Hello world!
SAMPLES>set x=##class(MyApp.Main.SampleClass).%New()
SAMPLES>set x.MessageCount=3
SAMPLES>do x.WriteIt()
Hello world! How are you?
Hello world! How are you?
Hello world! How are you?
クラス名ショートカット
クラスを参照する場合、以下のシナリオではパッケージ (または上位パッケージ) を省略できます。
-
参照が 1 つのクラス内であり、参照されるクラスが同じパッケージまたはサブパッケージ内にある場合。
-
参照が 1 つのクラス内であり、そのクラスが IMPORT 指示文を使用して、参照されるクラスを含むパッケージまたはサブパッケージをインポートする場合。
-
参照が 1 つのメソッド内であり、そのメソッドが IMPORT 指示文を使用して、参照されるクラスを含むパッケージまたはサブパッケージをインポートする場合。
-
%Library パッケージ内のクラスを参照している場合、これは特別に処理されます。クラス %Library.ClassName は %ClassName として参照できます。例えば、%Library.StringOpens in a new tab は %StringOpens in a new tab として参照できます。
-
User パッケージ内のクラスを参照している場合、これは特別に処理されます。例えば、User.MyClass は MyClass として参照できます。
インターシステムズでは、User パッケージにはクラスを提供していません。これは、ユーザが使用するために予約されています。
クラス・パラメータ
クラス・パラメータは、指定されたクラスのすべてのオブジェクトに対して同じ値を定義します。この値は、クラスがコンパイルするときに確立され、実行時に変更することはできません。クラス・パラメータは、以下の目的で使用します。
-
実行時に変更されない値を定義するため。
-
クラス定義に関するユーザ指定の情報を定義するため。クラス・パラメータは、単純な任意の名前と値の組み合わせです。この組み合わせを使用して、クラスに関する必要な情報を保存します。
-
プロパティとして使用する場合、さまざまなデータ型クラスの動作をカスタマイズするため (検証情報の提供など)。これについては、次のセクションで説明します。
-
使用するメソッド・ジェネレータ・メソッドに対して、パラメータ化された値を提供するため。
以下に、いくつかのパラメータを持つクラスを示します。
Class GSOP.DivideWS Extends %SOAP.WebService
{
Parameter USECLASSNAMESPACES = 1;
/// Name of the Web service.
Parameter SERVICENAME = "Divide";
/// SOAP namespace for the Web service
Parameter NAMESPACE = "http://www.mynamespace.org";
/// let this Web service understand only SOAP 1.2
Parameter SOAPVERSION = "1.2";
///further details omitted
}
プロパティ
Caché には、以下の 2 種類のプロパティがあります。
-
属性 - 値を保持します。この値は、以下のいずれかです。
-
1 つのリテラル値。通常、データ型に基づきます。
-
オブジェクト値 (これには、コレクション・オブジェクトとストリーム・オブジェクトがあります。どちらについても次の章で説明します)。
-
多次元配列。これはあまり一般的ではありません。
プロパティという用語は、関連付けを保持するプロパティではなく、単に、属性のプロパティを示すことがよくあります。
-
-
リレーションシップ - オブジェクト間の関連付けを保持します。
このセクションでは、これらのバリエーションのいくつかを示すプロパティ定義を含むサンプル・クラスを示します。
Class MyApp.Main.Patient Extends %Persistent
{
Property PatientID As %String [Required];
Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");
Property BirthDate As %Date;
Property Age As %Numeric [Transient];
Property MyTempArray [MultiDimensional];
Property PrimaryCarePhysician As Doctor;
Property Allergies As list Of PatientAllergy;
Relationship Diagnoses As PatientDiagnosis [ Cardinality = children, Inverse = Patient ];
}
以下のことに注意してください。
-
それぞれの定義では、As の後の項目はプロパティのタイプです。各タイプはクラスです。構文 As List Of は、特定のコレクション・クラスの省略表現です。これらについては、次の章で説明します。
%StringOpens in a new tab、%DateOpens in a new tab、および %NumericOpens in a new tab はデータ型クラスです。
%StringOpens in a new tab は既定のタイプです。
-
Diagnoses は、リレーションシップ・プロパティであり、残りは属性プロパティです。
-
PatientID、Gender、BirthDate、および Age は、単純なリテラル値のみを格納できます。
-
PatientID は Required キーワードを使用するため、必須です。つまり、このクラスのオブジェクトは、このプロパティの値を指定しない場合、保存できません。
-
Age は、他のリテラル・プロパティとは異なり、ディスクに保存されません。これは、それが Transient キーワードを使用するためです。
-
MyTempArray は MultiDimensional キーワードを使用するため、多次元プロパティです。このプロパティは既定では、ディスクに保存されません。
-
PrimaryCarePhysician および Allergies は、オブジェクト値プロパティ です。
-
Gender プロパティ定義には、プロパティ・パラメータの値が含まれます。これらは、このプロパティが使用するデータ型クラスのパラメータです。
このプロパティの値は、M と F に制限されます。論理値を表示すると (管理ポータルの場合など)、代わりに Male と Female が表示されます。各データ型クラスでは、LogicalToDisplay() などのメソッドが提供されます。
オブジェクト値プロパティおよびリレーションシップ・プロパティについては、次の章で説明します。
プロパティ・キーワードの指定
プロパティ定義では、プロパティの使用法に作用するオプションのプロパティ・キーワードを含めることができます。以下のリストに、よく使用されているキーワードのいくつかを示します。
このクラスのインスタンスをディスクに格納する前に、プロパティの値を設定する必要があることを指定します。既定では、プロパティは Required ではありません。サブクラスで、必要に応じてオプションのプロパティをマークできますが、その逆は実行できません。
プロパティの初期値を指定します。既定では、プロパティは初期値を持ちません。サブクラスは InitialExpression キーワードの値を継承し、それをオーバーライドできます。指定する値は、有効な ObjectScript 式とする必要があります (クラスが、Caché MVBasic など、他の言語で記述されている場合でも同様です)。
プロパティをデータベースに格納しないことを指定します。既定では、プロパティは Transient ではありません。サブクラスは Transient キーワードの値を継承しますが、それをオーバーライドできません。
プロパティがプライベートであることを指定します。サブクラスは Private キーワードの値を継承しますが、それをオーバーライドできません。
既定では、プロパティはパブリックであり、どのような場所でもアクセスできます。プロパティは (Private キーワードを使用して) プライベートとしてマークできます。その場合、それらが属するオブジェクトのメソッドによってのみアクセスできます。
Caché では、プライベート・プロパティは常に、プロパティを定義したクラスのサブクラスに継承され、参照できます。
他のプログラミング言語では、これらを保護されたプロパティと呼ぶことがあります。
このプロパティには、メモリ内ストレージを割り当てないことを指定します。既定では、プロパティは Calculated ではありません。サブクラスは Calculated キーワードを継承しますが、それをオーバーライドできません。
プロパティが多次元であることを指定します。このプロパティは、以下の点で他のプロパティとは異なります。
-
関連付けられているメソッドがありません (後続のトピックを参照)。
-
オブジェクトを検証または保存するときに、無視されます。
-
アプリケーションにそれを明示的に保存するコードが含まれていない場合、ディスクに保存されません。
-
ActiveX や Java によって公開できません。
-
SQL テーブルに格納できず、SQL テーブルでも公開されません。
多次元プロパティはあまり使用されませんが、オブジェクト状態情報を一時的に格納する場合に役立ちます。
データ型に基づくプロパティ
プロパティを定義し、そのタイプをデータ型クラスと指定する場合、このセクションで説明するように、そのプロパティを定義し、操作するための特別なオプションがあります。
データ型クラス
データ型クラスでは、プロパティの値に関する一連のルールを適用できます。
Caché には、%Library.StringOpens in a new tab、%Library.IntegerOpens in a new tab、%Library.NumericOpens in a new tab、%Library.DateOpens in a new tab、%MV.DateOpens in a new tab など多くのデータ型クラスが用意されています。%Library パッケージのクラスの名前は省略可能なため、これらの多くを省略できます。例えば、%DateOpens in a new tab は %Library.DateOpens in a new tab の省略形です。
各データ型クラスには、以下の機能があります。
-
コンパイラ・キーワードの値を指定します。プロパティの場合、コンパイラ・キーワードは、以下のようなことを実行できます。
-
プロパティを必須にします。
-
プロパティの初期値を指定します。
-
プロパティを SQL、ODBC、ActiveX、および Java クライアントに投影する方法を制御します。
-
-
以下のような詳細に影響を与えるパラメータの値を指定します。
-
データ型の論理値の最大値と最小値
-
文字列の最大文字数と最小文字数
-
小数点以下の桁数
-
最大文字数を超えた場合に文字列を切り捨てるかどうか
-
表示形式
-
特別な XML または HTML 文字のエスケープ方法
-
ユーザ・インタフェースで使用するための論理値および表示値の列挙リスト
-
文字列が一致する必要があるパターン (Caché パターン・マッチング演算子を自動的に使用)
-
XML のインポートまたは XML へのエクスポートの際に UTC タイム・ゾーンを尊重するか、無視するか
-
-
これは、リテラル・データを、格納形式 (ディスク上)、論理形式 (メモリ内)、表示形式の間で変換するための一連のメソッドを提供します。
独自のデータ型クラスを追加できます。例えば、以下は %Char のカスタム・サブクラスを示しています。
Class MyApp.MyType Extends %Library.Char
{
/// The maximum number of characters the string can contain.
Parameter MAXLEN As INTEGER = 2000;
}
データ型クラスのパラメータのオーバーライド
プロパティを定義し、そのタイプをデータ型クラスと指定する場合、そのデータ型クラスで定義されるどのパラメータもオーバーライドできます。
例えば、%IntegerOpens in a new tab データ型クラスは、クラス・パラメータ (MAXVAL) を定義しますが、このパラメータに対して値を提供しません。これを、プロパティ定義で以下のようにオーバーライドできます。
Property MyInteger As %Integer(MAXVAL=10);
このプロパティの場合、許容最大値は 10 です。
(データ型クラスの検証メソッドはメソッド・ジェネレータであるため、これは内部で機能します。指定するパラメータ値は、コンパイラがそのクラスのコードを生成するときに使用されます。メソッド・ジェネレータについては、後の “特別な種類のメソッド” で説明します。)
同様に、タイプ %StringOpens in a new tab のすべてのプロパティに照合タイプがあります。これにより、値を並べる方法 (先頭の文字の大文字化が有効かどうかなど) が決まります。既定の照合タイプは、SQLUPPERです。照合の詳細は、"Caché SQL の使用法" の “Caché SQL の基礎” の章にある “データ照合” を参照してください。
以下の別の例では、データ型クラスは、DISPLAYLIST および VALUELIST パラメータを定義します。これらを使用して、ユーザ・インタフェースに表示する選択肢と、それらに対応する内部値を指定できます。
Property Gender As %String(DISPLAYLIST = ",Female,Male", VALUELIST = ",F,M");
インスタンス変数の使用法
オブジェクトのインスタンス・メソッドの内部から、プロパティのメモリ内の値にアクセスするには、以下のメモリ内の値構文を使用できます。
Set i%Name = "Carl"
これは、NameSet アクセサ・メソッド (存在する場合) を使用せずに、“Carl“ をプロパティ Name のメモリ内の値として直接設定します。変数 i%Name はインスタンス変数です。"Caché オブジェクトの使用法" の “i%<PropertyName> 構文” を参照してください。アクセサ・メソッドの詳細は、同じドキュメントの “プロパティ・メソッドの使用とオーバーライド” の章を参照してください。
他のプロパティ・メソッドの使用法
プロパティには、自動的に関連付けられた多くのメソッドがあります。これらのメソッドは、データ型クラスによって生成されます。
例えば、3 つのプロパティでクラス Person を定義する場合、以下のようになります。
Class MyApp.Person Extends %Persistent
{
Property Name As %String;
Property Age As %Integer;
Property DOB As %Date;
}
生成された各メソッドの名前は、プロパティ名に継承クラスからのメソッド名を連結した名前です。例えば、DOB プロパティに関連付けられたメソッドでは以下のようになります。
Set x = person.DOBIsValid(person.DOB)
Write person.DOBLogicalToDisplay(person.DOB)
IsValid はプロパティ・クラスのメソッドで、LogicalToDisplay は %DateOpens in a new tab データ型クラスのメソッドです。
メソッド
インスタンス・メソッドとクラス・メソッド (他の言語では静的メソッドと呼ぶ) の 2 種類のメソッドがあります。多くの場合、メソッドはプロシージャです。
Method キーワードの指定
メソッド定義では、メソッドがどのように動作するかに作用するオプションのコンパイラ・キーワードを含めることができます。以下のリストに、よく使用されているメソッド・キーワードのいくつかを示します。
既定では、メソッドで使用される変数はそのメソッドに対してプライベートです。これは、既定では、すべてのメソッドがプロシージャ・ブロックであるためです。メソッドを非プロシージャ・ブロックとして定義するには、ProcedureBlock キーワードを 0 に指定します。以下に例を示します。
Method MyMethod() [ ProcedureBlock = 0 ]
{
//implementation details
}
この場合、このメソッドの変数は、パブリック変数になります。
Caché 内でサーバ側メソッドを作成するとき、実装言語を選択できます。選択肢は、basic (Caché Basic)、cache (ObjectScript)、mvbasic (MVBasic)、および tsql (TSQL) です。
既定で、メソッドはそのクラスに対して指定された Language キーワードによって指定された言語を使用します。多くの場合、そのキーワードは cache (ObjectScript) です。
メソッドがプライベートであることを指定します。サブクラスは Private キーワードの値を継承しますが、それをオーバーライドできません。
既定では、メソッドはパブリックであり、どのような場所でもアクセスできます。メソッドは (Private キーワードを使用して) プライベートとしてマークできます。その場合、
-
それらが属するクラスのメソッドによってのみアクセスできます。
-
インターシステムズ・クラス・リファレンスには記載されません。これについては、後の “インターシステムズ・クラス・リファレンス” で紹介します。
ただし、これは継承され、このメソッドを定義するクラスのサブクラスで使用できます。
他の言語では、このようなメソッドを保護されたメソッドと呼ぶことがあります。
他のクラス・メンバの参照
メソッド内で、ここに示す構文を使用し、他のクラスのメンバを参照します。
-
パラメータを参照するには、以下のような式を使用します。
..#PARAMETERNAME
インターシステムズが提供するクラスでは、慣例ですべてのパラメータがすべて大文字で定義されていますが、作成するコードでは大文字にしなくてもかまいません。
-
別のメソッドを参照するには、以下のような式を使用します。
..methodname(arguments)
この構文をクラス・メソッド内で使用して、インスタンス・メソッドを参照することはできません。
-
(インスタンス・メソッド内のみ) インスタンスのプロパティを参照するには、以下のような式を使用します。
..PropertyName
同様に、オブジェクト値プロパティのプロパティを参照するには、以下のような式を使用します。
..PropertyNameA.PropertyNameB
これを、Caché ドット構文といいます。
また、オブジェクト値プロパティのインスタンス・メソッド呼び出すこともできます。以下はその例です。
do ..PropertyName.MyMethod()
他のクラスのメソッドの参照
メソッド内で (またはルーチン内で)、ここに示す構文を使用し、他のクラスのメソッドを参照します。
-
クラス・メソッドを呼び出し、その返り値にアクセスするには、以下のような式を使用します。
##class(Package.Class).MethodName(arguments)
以下はその例です。
Set x=##class(Util.Utils).GetToday()
また、返り値にアクセスする必要がない場合は、DO を以下のように使用します。
Do ##class(Util.Utils).DumpValues()
Note:##class は、大文字と小文字を区別しません。
-
インスタンス・メソッドを呼び出すには、インスタンスを作成し (次の章を参照)、以下のような式を使用してそのメソッドを呼び出し、その返り値にアクセスします。
instance.MethodName(arguments)
以下はその例です。
Set x=instance.GetName()
また、返り値にアクセスする必要がない場合は、DO を以下のように使用します。
Do instance.InsertItem("abc")
返り値がないメソッドもあるので、自身の状況にあった構文を選択してください。
現在のインスタンスの参照
場合によっては、インスタンス・メソッド内で、そのインスタンスのメソッドのプロパティではなく、現在のインスタンス自体を参照することが必要になります。例えば、他のコードを呼び出すときに、現在のインスタンスを渡すことが必要な場合があります。そのような場合は、特殊変数 $THIS を使用して現在のインスタンスを参照します。
以下はその例です。
Set sc=header.ProcessService($this)
メソッド引数
メソッドは、コンマ区切りリストで位置を示す引数を取ります。引数ごとに、型および既定の値を指定できます。
例えば、以下は、3 つの引数を取るメソッドの定義の一部分です。
Method Calculate(count As %Integer, name, state As %String = "CA") as %Numeric
{
// ...
}
引数のうち 2 つが明示的な型を持ち、1 つが既定の値を持っています。一般的に、各引数の型を明示的に指定することは良い方法です。
引数のスキップ
ObjectScript では、メソッドを呼び出すときに、適切な既定の引数がある場合、それらの引数をスキップできます。例えば、以下は有効です。
set myval=##class(mypackage.myclass).GetValue(,,,,,,4)
値または参照による変数渡し
メソッドを呼び出す場合、ルーチンやサブルーチンの場合と同様に、値または参照によってそのメソッドに変数の値を渡します。このドキュメントで前述した “値または参照による変数渡し” を参照してください。
通常、メソッドのシグニチャは、参照による引数渡しを意図しているかどうかを示します。以下はその例です。
Method MyMethod(argument1, ByRef argument2, Output argument3)
ByRef キーワードは、参照によってこの引数を渡すことを示します。Output キーワードは、この引数を参照によって渡すことと、この引数に最初に指定した値がメソッドによってすべて無視されることを示します。
同様に、メソッドを定義するときに、メソッド・シグニチャで ByRef および Output キーワードを使用すると、そのメソッドの他のユーザに、それをどのように使用することを意図しているのかを知らせることができます。
ByRef および Output キーワードは、後で紹介するインターシステムズ・クラス・リファレンスの利用者全員に役立つ情報を提供します。これらのキーワードは、コードの動作には影響しません。メソッドの呼び出し方法に関する規則を適用するのは、メソッドの作成者の責任です。
可変の引数
引数の個数を変えることができるメソッドを定義できます。以下はその例です。
ClassMethod MultiArg(Arg1... As %List)
{
Write "Invocation has ",
$GET(Arg1, 0),
" element",
$SELECT(($GET(Arg1, 0)=1):"", 1:"s"),
!
For i = 1 : 1 : $GET(Arg1, 0)
{
Write:($DATA(Arg1(i))>0) "Argument[", i , "]:",
?15, $GET(Arg1(i), "<NULL>"), !
}
Quit
}
メソッドはプロシージャなので、... 構文を使用して引数の個数を変えることができます。この構文の説明は、"Caché ObjectScript の使用法" の “ユーザ定義コード” の章の “可変の引数” のセクションにあります。
既定値の指定
引数の既定値を指定するには、以下の例に示すように構文を使用します。
Method Test(flag As %Integer = 0)
{
//method details
}
メソッドが呼び出されるとき、引数が指定されていない場合は既定値を使用します (既定値が指定されている場合)。
もう 1 つの選択肢は $GET 関数を使用することです。以下はその例です。
Method Test(flag As %Integer)
{
set flag=$GET(flag,0)
//method details
}
ただし、この方法ではシグニチャに影響しません。
特別な種類のメソッド
CodeMode キーワードを使用すると、以下のような他の特別な種類のメソッドを定義できます。
呼び出しメソッド
呼び出しメソッドは、既存の Caché ルーチンの周囲のメソッド・ラッパを作成する、特別なメカニズムです。呼び出しメソッドの構文は以下のとおりです。
Method Call() [ CodeMode = call ]
{
Label^Routine
}
“Label^Routine” は、ルーチン内のラベルを指定します。
メソッド・ジェネレータ
メソッド・ジェネレータは、クラスのコンパイル中にクラス・コンパイラによって呼び出されるプログラムです。この出力は、メソッドの実際の実行時実装です。メソッド・ジェネレータは強力なクラス継承の方法を提供し、クラスやプロパティ継承の必要性に応じてカスタマイズされた、高性能で特別なコードを生成します。Caché ライブラリ内で、メソッド・ジェネレータは、データ型やストレージ・クラスによって広範囲に使用されます。
詳細は、"Caché ObjectScript の使用法" の “メソッド・ジェネレータ” の章を参照してください。
クラス・クエリ
Caché クラスには、クラス・クエリを含めることができます。クラス・クエリは、クラスが使用できる SQL クエリを定義し、クエリのためのコンテナとして使用するクラスを指定します。以下に例を示します。
Query QueryName(Parameter As %String) As %SQLQuery
{
SELECT MyProperty, MyOtherProperty FROM MyClass
WHERE (MyProperty = "Hello" AND MyOtherProperty = :Parameter)
ORDER BY MyProperty
}
アプリケーションで使用するための事前に定義された検索を提供するために、クラス・クエリを定義します。例えば、名前などの複数のプロパティによってインスタンスを検索したり、パリからマドリッドまでのすべての航空便など、一連の特定の条件に適合するインスタンスのリストを提供したりできます。ここに示した例では、パラメータを使用します。これは、柔軟なクエリを提供するための一般的な方法です。クラス・クエリはどのクラス内でも定義できます。クラス・クエリは永続クラス内に含める必要はありません。これについては、このドキュメントで後述します。
XData ブロック
XML は、多くの場合、構造化されたデータを表すための便利な方法であるため、Caché クラスには、どのようなニーズに対しても整形式 XML ドキュメントを含めることを可能にするメカニズムがあります。このためには、もう 1 つの種類のクラス・メンバである XData ブロックを含めます。以下に例を示します。
以下に例を示します。
XData Contents [XMLNamespace="http://www.intersystems.com/zen"]
{
<page xmlns="http://www.intersystems.com/zen" title="HelpDesk">
<html id="title">My Title</html>
<hgroup>
<pane paneName="menuPane"/>
<spacer width="20"/>
<vgroup width="100%" valign="top">
<pane paneName="tablePane"/>
<spacer height="20"/>
<pane paneName="detailPane"/>
</vgroup>
</hgroup>
</page>
}
Caché は、特定の目的のために XData ブロックを使用します。場合によっては、これらをユーザ自身のアプリケーションに活用することができます。
-
Zen ページでは、XData ブロックを使用して、ページの外観と使用感を記述します。
-
Caché Web サービスおよび Web クライアントに対する WS-Policy サポート。"Caché での Web サービスおよび Web クライアントの作成" を参照してください。この場合、XData ブロックはセキュリティ・ポリシーを記述します。
-
DeepSee では、XData ブロックを使用してキューブ、サブジェクト領域、KPI、およびその他の要素を定義します。
これらのすべての場合において、XData ブロックを、特定のタイプのクラス内に含める必要があります。
クラス定義におけるマクロとインクルード・ファイル
Caché クラス定義では、メソッド内にマクロを定義し、それらのマクロをそのメソッド内で使用できます。ただし、多くの場合、それらをインクルード・ファイル内で定義し、それをクラス定義の先頭でインクルードできます。以下はその例です。
Include (%assert, %callout, %occInclude, %occSAX)
/// Implements an interface to the XSLT Parser. XML contained in a file or binary stream
/// may be transformed
Class %XML.XSLT.Transformer Extends %RegisteredObject ...
その後、そのクラスのメソッドは、そのインクルード・ファイル、またはそれにインクルードされたインクルード・ファイルに定義されたマクロを参照できます。
マクロは継承されます。つまり、サブクラスは、そのスーパークラスと同じマクロすべてにアクセスできます。
Caché における継承規則
他のクラスベースの言語と同様に、複数のクラス定義を継承によって結合できます。Caché クラス定義は、複数の他のクラスを拡張 (または他のクラスから継承) できます。また、それらのクラスが他のクラスを拡張することもできます。
以下のサブセクションでは、Caché における継承の基本規則について説明します。
継承順序
Caché では、継承順序に次の規則を使用します。
-
既定では、特定の名前のクラス・メンバが複数のスーパークラスで定義されている場合、そのサブクラスはスーパークラス・リストの左端のクラスから定義を取ります。
-
クラス定義に Inheritance = right が含まれている場合、サブクラスはスーパークラス・リストの右端のクラスから定義を取ります。
これまでの使用法により、大部分の Caché クラスには、Inheritance = right が含まれています。
プライマリ・スーパークラス
他のクラスを拡張するクラスはすべて、1 つのプライマリ・スーパークラスを持っています。
クラスで使用される継承順序に関係なく、プライマリ・スーパークラスは、左から右に読む場合の最初のクラスです。
どのクラス・レベルのコンパイラ・キーワードについても、指定されたクラスは、そのプライマリ・スーパークラスで指定された値を使用します。
永続クラスの場合、プライマリ・スーパークラスは特に重要です。このドキュメントで後述する “クラスとエクステント” を参照してください。
最も適切なタイプのクラス
あるオブジェクトが複数のクラスのエクステント (いくつかのスーパークラスのエクステントなど) に属するインスタンスである場合でも、そのオブジェクトには必ず最も適切なタイプのクラス (MSTC) があります。オブジェクトがクラスのインスタンスであるが、そのクラスのどのサブクラスのインスタンスにもなっていない場合、そのクラスはそのオブジェクトの最も適切なタイプのクラスになります。
メソッドのオーバーライド
クラスは、その 1 つまたは複数のスーパークラスからメソッド (クラスおよびインスタンス・メソッドの両方) を継承し、それらはオーバーライドできます。その場合、自身のメソッド定義のシグニチャが、オーバーライドするメソッドのシグニチャと一致していることを確認する必要があります。これには、サブクラスのメソッドの引数と一致する、スーパークラスのメソッドの引数にデータ型が指定されていない場合は、そのサブクラスのメソッドの引数にデータ型を指定できないことも含まれます。ただし、サブクラスのメソッドで、そのスーパークラスに定義されていない追加の引数を指定することはできます。
サブクラスのメソッド内で、スーパークラス内のそれがオーバーライドしたメソッドを参照できます。そのためには、##super() 構文を使用します。以下はその例です。
//overrides method inherited from a superclass
Method MyMethod()
{
//execute MyMethod as implemented in the superclass
do ##super()
//do more things....
}
##super は、大文字と小文字を区別しません。
詳細
この章で説明したトピックの詳細は、以下のドキュメントを参照してください。
-
"Caché オブジェクトの使用法" には、Caché でのクラスおよびクラス・メンバの定義方法についての説明があります。
-
"Caché クラス定義リファレンス" には、クラス定義で使用するコンパイラ・キーワードのリファレンス情報があります。
-
“インターシステムズ・クラス・リファレンス” で後述するインターシステムズ・クラス・リファレンスには、Caché で提供されるすべての非内部クラスの詳細な情報があります。