登録オブジェクトを使用した作業
%RegisteredObjectOpens in a new tab クラスは、InterSystems IRIS® データ・プラットフォームの基本オブジェクト API です。ここでは、この API の使用方法について説明します。このトピックの情報は、%RegisteredObjectOpens in a new tab のすべてのサブクラスに適用されます。
オブジェクト・クラスの概要
オブジェクト・クラス とは、%RegisteredObjectOpens in a new tab を継承するあらゆるクラスのことです。オブジェクト・クラスでは、以下のことが実行できます。
-
クラスのインスタンスの作成。これに該当するインスタンスをオブジェクトと呼びます。
-
これに該当するオブジェクトのプロパティの設定。
-
これに該当するオブジェクトのメソッド (インスタンス・メソッド) の呼び出し。
これらのタスクはオブジェクト・クラスでのみ可能です。
%PersistentOpens in a new tab クラスおよび %SerialObjectOpens in a new tab クラスは、%RegisteredObjectOpens in a new tab のサブクラスです。概要は、"オブジェクト・クラス" を参照してください。
OREF の基本
オブジェクトを作成すると、そのオブジェクトについての情報を保持するメモリ内構造がシステムによって作成されます。また、その構造へのポインタである OREF (オブジェクト参照) も作成されます。
オブジェクト・クラスには、OREF を作成する複数のメソッドがあります。どのようなオブジェクト・クラスを使用するときにも、広範囲にわたって OREF を使用することになります。これを使用してオブジェクトのプロパティ値を指定し、オブジェクトのプロパティ値にアクセスし、オブジェクトのインスタンス・メソッドを呼び出します。以下の例を考えてみます。
MYNAMESPACE>set person=##class(Sample.Person).%New()
MYNAMESPACE>set person.Name="Carter,Jacob N."
MYNAMESPACE>do person.PrintPerson()
Name: Carter,Jacob N.
最初の手順では、Sample.Person という名前のクラスの %New() メソッドを呼び出しています。このメソッドは、オブジェクトを作成して、そのオブジェクトをポイントする OREF を返します。この OREF と等しくなるように、変数 person を設定します。その次の手順では、オブジェクトの Name プロパティを設定しています。3 番目の手順では、オブジェクトの PrintPerson() インスタンス・メソッドを呼び出しています。(Name プロパティと PrintPerson() メソッドは、どちらも単なる例です。これらは Sample.Person クラスで定義されていますが、汎用オブジェクト・インタフェースの一部ではありません。)
OREF は一時的なものです。その値はオブジェクトがメモリ内にあるときにだけ存在し、呼び出しのたびに値が同じになることは保証されていません。
OREF はそれが作成されたネームスペース内でのみ有効です。したがって、既存の OREF が存在しているときに現在のネームスペースを変更すると、前のネームスペースからの OREF は無効になります。別のネームスペースからの OREF を使用してみたときに、即時にエラーが発生しないことがありますが、その結果から OREF が有効または使用可能であると見なすことはできず、現行のネームスペースでは深刻な状況が発生する可能性があります。
INVALID OREF エラー
単純な式で、変数のプロパティを設定する場合や変数のプロパティにアクセスする場合、または変数のインスタンス・メソッドを呼び出す場合に、その変数が OREF でないと、<INVALID OREF> エラーを受け取ることになります。以下に例を示します。
MYNAMESPACE>write p2.PrintPerson()
WRITE p2.PrintPerson()
^
<INVALID OREF>
MYNAMESPACE>set p2.Name="Dixby,Jase"
SET p2.Name="Dixby,Jase"
^
<INVALID OREF>
OREF のテスト
InterSystems IRIS には、$ISOBJECT という関数があります。この関数を使用すると、特定の変数が OREF を保持しているかどうかをテストできます。この関数は、変数に OREF が格納されている場合に 1 を返します。それ以外の場合は 0 を返します。特定の変数が OREF を格納していない可能性のある場面では、変数のプロパティを設定する前や変数のプロパティにアクセスする前、または変数のインスタンス・メソッドを呼び出す前に、この関数を使用するようお勧めします。
OREF、スコープおよびメモリ
あらゆる OREF はメモリ内のオブジェクトへのポインタであり、そのオブジェクトは別の OREF がポイントしている可能性があります。つまり、OREF (変数) は、メモリ内のオブジェクトとは別のものであるということです (ただし、実際には OREF という用語とオブジェクトという用語は、ほとんどの場合に同じ意味で使用されます)。
InterSystems IRIS では、メモリ内の構造が以下のように自動的に管理されます。メモリ内のオブジェクトごとに、InterSystems IRIS は参照カウント (そのオブジェクトへの参照数) を維持します。変数やオブジェクトのプロパティにオブジェクトへの参照を設定すると、常に、そのオブジェクトの参照カウントが自動的にインクリメントされるようになります。変数がオブジェクトへの参照を停止すると (範囲外になった場合、削除された場合、または新しい値が設定された場合)、そのオブジェクトの参照カウントはデクリメントされます。このカウントが 0 に達すると、オブジェクトは自動的に消滅し (メモリから削除され)、%OnClose() メソッド (存在する場合) が呼び出されます。
例えば、以下のメソッドを考えてみます。
Method Test()
{
Set person = ##class(Sample.Person).%OpenId(1)
Set person = ##class(Sample.Person).%OpenId(2)
}
このメソッドは Sample.Person のインスタンスを作成し、そのインスタンスに対する参照を変数 person に配置します。そして、Sample.Person の別のインスタンスを作成し、person の値を新しいインスタンスに対する参照に変更します。ここで、最初のオブジェクトは参照しているものがなくなり、消滅します。メソッドの最後で、person は範囲外になり、2 番目のオブジェクトは消滅します。
OREF の削除
必要に応じて、KILL コマンドを以下のように使用することで、OREF を削除できます。
kill OREF
この OREF は、OREF を格納している変数です。このコマンドにより、変数が削除されます。オブジェクトへの参照がなくなった場合は、前述したように、このコマンドによりオブジェクトもメモリから削除されます。
OREF、SET コマンド、およびシステム関数
一部のシステム関数 ($Piece、$Extract、$List など) について、InterSystems IRIS では既存の値を変更するために使用できる代替構文をサポートしています。この構文では、以下のように、SET コマンドと関数を組み合わせます。
SET function_expression = value
function_expression はシステム関数の呼び出し (引数付き) であり、value は値です。例えば、以下の文では、"Magenta" と等しくなるように colorlist 文字列の最初の部分を設定しています。
SET $PIECE(colorlist,",",1)="Magenta"
この方法で OREF やそのプロパティを変更することはサポートされていません。
$DATA()、$GET()、および $INCREMENT() は、プロパティが多次元である場合にのみ、プロパティを引数として取ることができます。これらの処理は、インスタンス変数構文 i%PropertyName を使用してオブジェクト・メソッド内で実行できます。プロパティを MERGE コマンドで使用することはできません。
新しいオブジェクトの作成
特定のオブジェクト・クラスの新しいインスタンスを作成するには、そのクラスのクラス・メソッド %New() を使用します。このメソッドにより、オブジェクトが作成され、OREF が返されます。以下に例を示します。
Set person = ##class(MyApp.Person).%New()
%New() メソッドは 1 つの引数を受け入れます。この引数は、既定では無視されます。存在する場合、この引数はクラスの %OnNew() コールバック・メソッドに渡されます (定義されている場合)。%OnNew() が定義されている場合は、新しく作成したオブジェクトを初期化するために引数を使用できます。詳細は、"コールバック・メソッドの実装" を参照してください。
特定のクラスの新規オブジェクトを作成する方法に影響を与える複雑な要件がある場合は、そのクラスのインスタンスを作成するために使用する代替のメソッドを用意できます。そのようなメソッドでは、%New() を呼び出してから、必要に応じてオブジェクトのプロパティを初期化することになります。このようなメソッドは、ファクトリ・メソッドと呼ばれることがあります。
オブジェクトのコンテンツの表示
WRITE コマンドは、OREF について、以下の形式の出力を書き込みます。
n@Classname
Classname は、クラスの名前です。また、n は、このクラスのメモリ内の特定のインスタンスを示す整数です。以下に例を示します。
MYNAMESPACE>write p
8@Sample.Person
ZWRITE コマンドを OREF に使用すると、InterSystems IRIS は関連するオブジェクトについての詳細な情報を表示します。
MYNAMESPACE>zwrite p
p=<OBJECT REFERENCE>[8@Sample.Person]
+----------------- general information ---------------
| oref value: 1
| class name: Sample.Person
| %%OID: $lb("3","Sample.Person")
| reference count: 2
+----------------- attribute values ------------------
| %Concurrency = 1 <Set>
| DOB = 33589
| Name = "Clay,George O."
| SSN = "480-57-8360"
+----------------- swizzled references ---------------
| i%FavoriteColors = "" <Set>
| r%FavoriteColors = "" <Set>
| i%Home = $lb("5845 Washington Blvd","St Louis","NM",55683) <Set>
| r%Home = "" <Set>
| i%Office = $lb("3413 Elm Place","Pueblo","WI",98532) <Set>
| r%Office = "" <Set>
| i%Spouse = ""
| r%Spouse = ""
+-----------------------------------------------------
この情報には、オブジェクトに関して、クラス名、OID、参照カウント、およびプロパティの現在の値 (メモリ内) が表示される点に注目してください。swizzled references のセクションでは、i% で始まる名前の項目がインスタンス変数です。(r% で始まる名前の項目は、内部使用専用です。)
ドット構文の概要
OREF では、ドット構文を使用して、関連するオブジェクトのプロパティとメソッドを参照できます。このセクションでは、ドット構文の概要について説明します。ドット構文については、オブジェクトのメソッドとプロパティを参照する代替手段と共に後続のセクションでも説明します。
一般的なドット構文は、以下のようになります。
oref.membername
例えば、オブジェクトのプロパティの値を指定する場合は、以下のような文を使用できます。
Set oref.PropertyName = value
oref は特定のオブジェクトの OREF で、PropertyName は設定するプロパティの名前です。value は、目的の値に評価される ObjectScript 式です。これは、定数でも複雑な式でもかまいません。
同じ構文をオブジェクトのメソッド (インスタンス・メソッド) の呼び出しに使用できます。インスタンス・メソッドは、クラスの特定のインスタンスから呼び出され、通常はそのインスタンスに関連するアクションを実行します。以下の例では、Name プロパティを設定したばかりのオブジェクトの PrintPerson() メソッドを呼び出しています。
set person=##class(Sample.Person).%New()
set person.Name="Carter,Jacob N."
do person.PrintPerson()
メソッドが値を返す場合は、以下のように SET コマンドを使用することで、返り値を変数に代入できます。
SET myvar=oref.MethodName()
メソッドが値を返さない場合 (または、返り値を無視する場合) は、以下のように DO を使用するか JOB を使用します。
Do oref.MethodName()
メソッドが引数を受け入れる場合は、括弧で囲んで引数を指定します。
Set value = oref.methodName(arglist)
カスケード・ドット構文
クラス定義によっては、プロパティがオブジェクト値になることがあります。これは、そのプロパティのタイプがオブジェクト・クラスであることを意味します。このような場合は、OREF のチェーンを使用することで、複数のプロパティのうちの 1 つのプロパティ (または、プロパティのメソッド) を参照できます。これを、カスケード・ドット構文といいます。例えば、以下の構文では、Person オブジェクトの HomeAddress プロパティのうちの Street プロパティを参照しています。
set person.HomeAddress.Street="15 Mulberry Street"
この例では、person 変数は OREF であり、式 person.HomeAddress も OREF です。
一般に、クラス・メンバを参照するときには、非公式の参照である PackageName.ClassName.Member (例えば、Accounting.Invoice.LineItem プロパティ) を使用することがあります。この形式がコード内に現れることはありません。
NULL OREF が含まれたカスケード・ドット構文
プロパティを参照するために OREF のチェーンを使用しているときに、中間オブジェクトが設定されていない場合、一般に、そのオブジェクトに関する <INVALID OREF> エラーを受け取るよりも、式に NULL 文字列を返したほうが好都合になります。そのため、中間オブジェクトが設定されていない (NULL 文字列と等しくなる) 場合、チェーンによるプロパティの参照には NULL 文字列の値が返されます。
例えば、pers が Sample.Person の有効なインスタンスであり、pers.Spouse が "" と等しい場合、以下の文では name 変数に "" が設定されます。
set name=pers.Spouse.Name
この動作が適していないコンテキストでは、中間オブジェクトの参照をコードで明示的にチェックする必要があります。
オブジェクトの検証
%RegisteredObjectOpens in a new tab クラスには、インスタンスのプロパティを検証する %ValidateObject, メソッドが用意されています。このメソッドは、以下の条件に当てはまる場合、1 を返します。
-
すべての必須プロパティに値がある。プロパティを必須にするには、Required キーワードを使用します。プロパティのタイプが %StreamOpens in a new tab の場合、そのストリームを null ストリームにできません。つまり、そのプロパティに、%IsNull() メソッドが 1 を返す値を指定することはできません。
-
各プロパティの値が (NULL でない場合)、それに関連付けられたプロパティ定義に照らして有効である。
例えば、プロパティのタイプが %BooleanOpens in a new tab の場合、値 "abc" は有効ではありませんが、値 0 と値 1 は有効です。
-
各リテラル・プロパティの値が (NULL でない場合)、プロパティ定義で定義されたすべての制約に従っている。制約という用語は、プロパティ値に制限を適用するプロパティ・キーワードを指します。例えば、MAXLEN、MAXVAL、MINVAL、VALUELIST、PATTERN などです。完全なリストは、"リテラル・プロパティの定義と使用" を参照してください。
例えば、あるプロパティのタイプが %StringOpens in a new tab で MAXLEN の既定値が 50 の場合、そのプロパティは 50 文字以下の長さに制限されます。
-
オブジェクト値プロパティの場合、参照されるオブジェクトのすべてのプロパティが前述のルールに従っている。
%ValidateObject() は、各プロパティの検証ロジックを順番に呼び出します。詳細は、"プロパティ・メソッドの使用とオーバーライド" を参照してください。
いずれかのプロパティが検証チェックに失敗した場合、このメソッドはエラー・ステータスを返します。
Sample.Person クラスを見てみましょう。このクラスのオブジェクトには、必須の社会保障番号プロパティ SSN が含まれます。このプロパティは、NNN-NN-NNNN の形式で指定されている必要があります。
Property SSN As %String(PATTERN = "3N1""-""2N1""-""4N") [ Required ];
Sample.Person オブジェクトを新規作成し、このプロパティを含めていない場合、%ValidateObject() は、このプロパティが欠落していてパターンに一致しないことを示すエラー・ステータスを返します。
set person = ##class(Sample.Person).%New()
set status = person.%ValidateObject()
do $system.OBJ.DisplayError(status)
ERROR #5659: Property 'Sample.Person::SSN(9@Demo.Person,ID=)' required
ERROR #7209: Datatype value '' does not match PATTERN '3N1"-"2N1"-"4N'
> ERROR #5802: Datatype validation failed on property 'Sample.Person:SSN', with value equal to ""
このプロパティを設定しても指定パターンに一致しない場合、%ValidateObject() は、パターン・マッチングのエラー・ステータスのみを返します。
set person.SSN = "0000000000"
set status = person.%ValidateObject()
do $system.OBJ.DisplayError(status)
ERROR #7209: Datatype value '' does not match PATTERN '3N1"-"2N1"-"4N'
> ERROR #5802: Datatype validation failed on property 'Sample.Person:SSN', with value equal to ""
このプロパティを適切に設定すると、このオブジェクトは %ValidateObject() チェックに合格し、ステータス 1 を返します。
永続オブジェクトが有効と見なされるためには、そのプロパティが、定義済みのどの一意制約にも違反していない必要もあります。%ValidateObject() は、一意性をチェックしません。このチェックの対象はオブジェクト内のプロパティに限られ、データベースに保存される他のオブジェクトのプロパティはチェックの対象とならないためです。一意性のチェックは、%Save() を呼び出してオブジェクトを保存するときに行われます。
前述の例を基に、Sample.Person クラスで SSN プロパティを一意とするよう制約するとします。
Index SSNIndex On SSN [ Unique ]
新しい person を作成して、前の person と同じ社会保障番号を設定すると、%ValidateObject() はステータス 1 を返し、$system.OBJ.DisplayError はこのステータスに対してエラーを表示しません。
do person.%Save() // Save first object to database
set person2 = ##class(Sample.Person).%New()
set person2.SSN = "000-00-0000"
set status = person2.%ValidateObject()
do $system.OBJ.DisplayError(status)
ただし、このオブジェクトをデータベースに保存しようとすると失敗します。これは、SSN プロパティに一意制約が適用されているためです。
set status = person2.%Save()
do $system.OBJ.DisplayError(status)
ERROR #5808: Key not unique: Sample.Person:SSNIndex:^Sample.PersonI("SSNIndex"," 000-00-0000")
永続オブジェクトを保存する場合は、自動的に %ValidateObject() メソッドが最初に呼び出されます。オブジェクトがこのチェックに失敗し、さらに一意性チェックにも失敗した場合、このオブジェクトは保存されません。詳細は、"永続オブジェクトの概要" を参照してください。
オブジェクト・タイプの判別
オブジェクトが存在すれば、%RegisteredObjectOpens in a new tab クラスに、そのオブジェクトの継承を判断するためのメソッドがあります。このセクションでは、これについて説明します。
%Extends()
オブジェクトが特定のスーパークラスを継承しているかどうかを確認するには、そのオブジェクトの %Extends() メソッドを呼び出して、スーパークラスの名前を引数として渡します。このメソッドから 1 が返される場合、インスタンスは、そのクラスを継承しています。0 が返される場合、インスタンスは、そのクラスを継承していません。以下に例を示します。
MYNAMESPACE>set person=##class(Sample.Person).%New()
MYNAMESPACE>w person.%Extends("%RegisteredObject")
1
MYNAMESPACE>w person.%Extends("Sample.Person")
1
MYNAMESPACE>w person.%Extends("Sample.Employee")
0
%IsA()
オブジェクトにプライマリ・スーパークラスとして特定のクラスがあるかどうかを確認するには、そのオブジェクトの %IsA() メソッドを呼び出して、スーパークラスの名前を引数として渡します。このメソッドから 1 が返される場合、オブジェクトには特定クラスがそのプライマリ・スーパークラスとして存在します。
%ClassName() および最も適切なタイプのクラス (MSTC)
オブジェクトは複数のクラスのうちの 1 つのインスタンスである可能性がありますが、オブジェクトには必ず 1 つの 最も適切なタイプのクラス (MSTC) があります。オブジェクトがクラスのインスタンスであり、さらにそのクラスのどのサブクラスのインスタンスにもなっていない場合、そのクラスはそのオブジェクトの最も適切なタイプのクラスとなります。
例えば、GradStudent クラスが Student クラスを継承し、Student クラスが Person クラスを継承する場合に、以下のコマンドで作成するインスタンスについて考えてみます。
set MyInstance1 = ##class(MyPackage.Student).%New()
set MyInstance2 = ##class(MyPackage.GradStudent).%New()
MyInstance1 に対しては Student が MSTC になります。それは、MyInstance1 は Person と Student のインスタンスですが、GradStudent のインスタンスではないからです。MyInstance2 に対しては GradStudent が MSTC になります。それは、MyInstance2 が GradStudent、Student、および Person のインスタンスであるからです。
オブジェクトの MSTC に関しては、以下のルールも適用されます。
-
オブジェクトの MSTC はプライマリ継承にのみ基づきます。
-
インスタンス化できないクラスは、オブジェクトの MSTC になることはできません。オブジェクト・クラスは、インスタンス化できません (そのクラスが抽象の場合)。
オブジェクトの MSTC を確認するには、%RegisteredObjectOpens in a new tab から継承された %ClassName() メソッドを以下のように使用します。
classmethod %ClassName(fullname As %Boolean) as %String
fullname はブーリアン引数です。1 はこのメソッドでパッケージ名とクラス名を返すことを指定し、0 (既定) はこのメソッドでクラス名のみを返すことを指定します。
例 :
write myinstance.%ClassName(1)
(同様に、%PackageName() を使用すると、パッケージの名前だけを取得できます。)
オブジェクトのクローン化
オブジェクトをクローン化するには、そのオブジェクトの %ConstructClone() メソッドを呼び出します。このメソッドが新規の OREF を作成します。
下記のターミナル・セッションでこれを示します。
MYNAMESPACE>set person=##class(Sample.Person).%OpenId(1)
MYNAMESPACE>set NewPerson=person.%ConstructClone()
MYNAMESPACE>w
NewPerson=<OBJECT REFERENCE>[2@Sample.Person]
person=<OBJECT REFERENCE>[1@Sample.Person]
MYNAMESPACE>
ここで、NewPerson 変数が元の person オブジェクトとは異なる OREF を使用していることがわかります。NewPerson は person のクローンです (より正確には、それらの変数は別の同一オブジェクトのポインタです)。
一方、以下のターミナル・セッションを考えてみます。
MYNAMESPACE>set person=##class(Sample.Person).%OpenId(1)
MYNAMESPACE>set NotNew=person
MYNAMESPACE>w
NotNew=<OBJECT REFERENCE>[1@Sample.Person]
person=<OBJECT REFERENCE>[1@Sample.Person]
ここで、両変数が同じ OREF を参照していることに注意してください。つまり、NotNew は person のクローンではありません。
このメソッドの引数の詳細は、"インターシステムズ・クラス・リファレンス" で %Library.RegisteredObjectOpens in a new tab を参照してください。
インスタンスのプロパティの参照
インスタンスのプロパティを参照するには、以下のいずれかを実行します。
-
関連するクラスのインスタンスを作成し、前述したようにドット構文を使用して、そのインスタンスのプロパティを参照します。
-
関連するクラスのインスタンス・メソッド内で、以下に示すように、相対ドット構文を使用します。
..PropName
この式は、SET コマンドと共に使用することも、別の式の一部として使用することもできます。以下に、いくつかのバリエーションを示します。
set value=..PropName write ..PropName
-
実行時までプロパティ名が決定されないプロパティにアクセスするには、$PROPERTY 関数を使用します。プロパティが多次元の場合、プロパティの値にアクセスするときのインデックスとして、プロパティ名に続く引数を使用します。このシグニチャは以下のようになります。
$PROPERTY (oref, propertyName, subscript1, subscript2, subscript3... )
oref は OREF です。propertyName は関連するクラスのプロパティ・メソッドの名前に評価されます。また、subscript1、subscript2、subscript3 は、プロパティの添え字に対応する値です (多次元プロパティの場合にのみ指定します)。
詳細は、"$PROPERTY" を参照してください。
-
(インスタンス・メソッド内で) 変数 $this を使用します。
-
(インスタンス・メソッド内で) インスタンス変数を使用します。
-
適切なプロパティ・アクセサ (ゲッターおよびセッター) メソッドを使用します。"プロパティ・メソッドの使用とオーバーライド" を参照してください。
インスタンスのメソッドの呼び出し
インスタンスのメソッドを呼び出すには、以下のいずれかを実行できます。
-
関連するクラスのインスタンスを作成し、前述したようにドット構文を使用して、そのインスタンスのメソッドを呼び出します。
-
(インスタンス・メソッド内で) 以下の式を使用して、そのクラスの別のインスタンス・メソッド (継承されたメソッドでもかまいません) を呼び出します。
..MethodName(args)
この式は DO コマンドと共に使用できます。メソッドが値を返す場合は、SET を使用することも、別の式の一部として使用することもできます。以下に、いくつかのバリエーションを示します。
do ..MethodName() set value=..MethodName(args)
-
実行時までメソッド名が決定されないインスタンス・メソッドを実行するには、以下のように $METHOD 関数を使用します。
$METHOD(oref, methodname, Arg1, Arg2, Arg3, ... )
oref は OREF です。methodname は関連するクラスのインスタンス・メソッドの名前に評価されます。また、Arg1、Arg2、Arg3 などは、そのメソッドの引数です。
詳細は、"$METHOD" を参照してください。
-
(インスタンス・メソッド内で) 変数 $this を使用します。
インスタンスからのクラス名の取得
クラスの名前を取得するには、以下のように $CLASSNAME 関数を使用します。
$CLASSNAME(oref)
oref は OREF です。
詳細は、"$CLASSNAME" を参照してください。
$this 変数 (現在のインスタンス)
$this 構文は、現在のインスタンスの OREF へのハンドルを提供します。例えば、現在のインスタンスを別のクラスに渡したり、別のクラスが現在のインスタンスのメソッドのプロパティを参照するために使用します。インスタンスが、そのインスタンスのプロパティやメソッドを参照する場合は、相対ドット構文のほうが高速であるために推奨されています。
$this は大文字と小文字を区別しません。このため、$this、$This、$THIS、およびその他の変異形は同じ値を持ちます。
例えば、Accounting.Order クラスと Accounting.Utils クラスを持つアプリケーションがあるとします。Accounting.Order.CalcTax() メソッドは、Accounting.Utils.GetTaxRate() メソッドおよび Accounting.Utils.GetTaxableSubtotal() メソッドを呼び出し、現在のインスタンスの "city" と "state" の値を GetTaxRate() メソッドに渡し、注文された品目と関連する税金関係の情報のリストを GetTaxableSubtotal() に渡します。CalcTax() は、返された値を使用して、注文に対する消費税を算出します。従って、コードは以下のようになります。
Method CalcTax() As %Numeric
{
Set TaxRate = ##class(Accounting.Utils).GetTaxRate($this)
Write "The tax rate for ",..City,", ",..State," is ",TaxRate*100,"%",!
Set TaxableSubtotal = ##class(Accounting.Utils).GetTaxableSubTotal($this)
Write "The taxable subtotal for this order is $",TaxableSubtotal,!
Set Tax = TaxableSubtotal * TaxRate
Write "The tax for this order is $",Tax,!
}
メソッドの最初の行では、##Class 構文 (前述) を使用して別のメソッドを呼び出しています。ここでは $this 構文を使用して、そのメソッドに現在のオブジェクトを渡します。メソッドの 2 行目では、.. 構文 (前述) を使用して、City プロパティおよび State プロパティの値を取得しています。3 行目の動作は、1 行目と同様です。
Accounting.Utils の GetTaxRate() メソッドは、渡されたインスタンスのハンドルを使用して、さまざまなプロパティへのハンドルを (値を取得したり設定したりするために) 取得します。
ClassMethod GetTaxRate(OrderBeingProcessed As Accounting.Order) As %Numeric
{
Set LocalCity = OrderBeingProcessed.City
Set LocalState = OrderBeingProcessed.State
// code to determine tax rate based on location and set
// the value of OrderBeingProcessed.TaxRate accordingly
Quit OrderBeingProcessed.TaxRate
}
GetTaxableSubtotal() もインスタンスのハンドルを使用し、そのプロパティを確認して TaxableSubtotal プロパティの値を設定します。
そのため、Accounting.Order クラスの MyOrder インスタンスにある CalcTax() メソッドを呼び出すと、以下のような内容が表示されます。
>Do MyOrder.CalcTax() The tax rate for Cambridge, MA is 5% The taxable subtotal for this order is $79.82 The tax for this order is $3.99
i%PropertyName (インスタンス変数)
このセクションでは、インスタンス変数の概要について説明します。このような変数は、プロパティのアクセサ・メソッドをオーバーライドしていない場合は参照する必要がありません。これについては、"プロパティ・メソッドの使用とオーバーライド" を参照してください。
どのようなクラスのインスタンスを作成するときでも、システムは、そのクラスの非計算プロパティごとに 1 つのインスタンス変数を作成します。インスタンス変数は、プロパティの値を保持します。プロパティ PropName の場合、インスタンス変数には i%PropName という名前が付けられます。この変数名は、大文字と小文字が区別されます。このような変数は、クラスのインスタンス・メソッド内で使用できます。
例えば、あるクラスにプロパティ Name と DOB がある場合は、そのクラスのあらゆるインスタンス・メソッド内で、インスタンス変数 i%Name と i%DOB を使用できます。
InterSystems IRIS では、r%PropName や m%PropName という名前の付いた追加のインスタンス変数も内部的に使用しますが、このような変数の直接使用はサポートされていません。
インスタンス変数は、その変数に割り当てられたプロセス・プライベートのメモリ内領域を保持します。このような変数は、ローカル変数シンボル・テーブルに保持されないため、Kill コマンドの影響は受けません。