クラス定義のプロパティ表示順と、プロパティに対応したグローバル変数の格納順
これは InterSystems FAQ サイトの記事です。
クラス定義のプロパティの表示順は、スタジオのプロパティウィザードを利用して登録した場合は、末尾に追記されます。
また、エディタ上の任意の場所でプロパティ定義文を記述する場合は、その場所に追記され、クラス定義が登録されます。
つまり、定義者が記述した順番に登録されます。
(スタジオが並び換えを行ったりはしません。)
作成したクラス定義が、PersistentやSerialのようにデータベースに格納する属性を持ったクラス定義である場合、”初回のコンパイル”で クラス定義に対応するグローバル変数の定義情報=ストレージ定義を作成します。
初回コンパイル以降に、プロパティ定義の追加が行われれば、そのプロパティに対応するグローバル変数のスロット番号を、末尾に追加し、ストレージ定義を更新します。
以下の例は、クラス定義に対応するストレージ定義の例です。
(初回コンパイル時の状態)
Class Sample.Person Extends %Persistent
{ Property Name As %String; /// 誕生日
Property DOB As %Date; <storage name="Default">
<data name="PersonDefaultData">
<value name="1">
<value>%%CLASSNAME</value></value> <value name="2">
<value>Name</value></value> <value name="3">
<value>DOB</value></value></data> <datalocation>^Sample.PersonD</datalocation>
<defaultdata>PersonDefaultData</defaultdata>
<extentsize>100000</extentsize>
<idlocation>^Sample.PersonD</idlocation>
<indexlocation>^Sample.PersonI</indexlocation>
<streamlocation>^Sample.PersonS</streamlocation>
<type>%Library.CacheStorage</type></storage> }
<storage name="Default">から</storage>までの表示が、クラス定義の初回コンパイルで作成されるストレージ定義情報です。
作成したSample.Personクラスの格納先グローバル変数は、ストレージ定義の<datalocation> <indexlocation> <streamlocatoin> を参照するとわかります。
また、各プロパティ定義が、指定グローバル変数のどこに格納されるかは、<value name="2"> と <value name="3">を参照するとわかります。
<value name="2">
<value>Name</value>%lt;/value> <value name="3">
<value>DOB</value></value>
つまり、Nameプロパティは、^Sample.PersonDの $ListBuild()構造の2番目に格納され、DOBは3番目に格納されることがわかります。
ここで、Addressプロパティを、クラス定義の表示上、一番上に追加します。
Class Sample.Person Extends %Persistent
{ Property Address As %String; Property Name As %String; /// 誕生日
Property DOB As %Date; <storage name="Default">
<data name="PersonDefaultData">
<value name="1">
<value>%%CLASSNAME</value></value> <value name="2">
<value>Name</value></value> <value name="3">
<value>DOB</value></value> <value name="4">
<value>Address</value></value></data> <datalocation>^Sample.PersonD</datalocation>
<defaultdata>PersonDefaultData</defaultdata>
<extentsize>100000</extentsize>
<idlocation>^Sample.PersonD</idlocation>
<indexlocation>^Sample.PersonI</indexlocation>
<streamlocation>^Sample.PersonS</streamlocation>
<type>%Library.CacheStorage</type> }
ストレージ定義情報を参照すると、クラス定義の表示上1番上に登録したAddressプロパティは、
<value name="4">
<value>Address</value></value>
$ListBuildの4番目に格納される定義として追加されています。
つまり、ストレージ定義は、クラス定義の表示上、どこに追記されても、後から追加されたプロパティについては、格納位置として、一番最後に追加していく仕組みがわかります。
ということで、クラス定義上の表示順と、ストレージ定義の格納順は必ずしも一致しない事があります。
なお、ストレージの格納順序を変更することはできます。
以下の例は、AddressとNameの格納順を、
≪現在≫
Address → 4番目
Name → 2番目
≪変更後≫
Address → 2番目
Name → 4番目
に変更した状態のストレージ定義例です。(一部抜粋)
<data name="PersonDefaultData">
<value name="1">
<value>%%CLASSNAME</value></value> <value name="4">
<value>Name</value></value> <value name="3">
<value>DOB</value></value> <value name="2">
<value>Address</value></value></data>
ご覧いただいた通り、AddressプロパティとNameプロパティのスロット番号を入れ替えるだけで、ストレージ定義の格納順の変更が行えます。
ただ、ストレージ定義情報の順番のみが入れ替わるだけであり、既存グローバル変数のデータが入れ替わる事はありません。
この点、ご注意ください。
(修正したストレージ定義に合わせて、グローバル変数を入れ替えたい場合は、手動でグローバル変数の中身を変更する必要があります。)