プロパティ・メソッドのオーバーライド
ここでは、プロパティ・メソッドをオーバーライドする方法について説明します。OREF を使用してオブジェクトのプロパティを操作するとき、プロパティ・メソッドは InterSystems IRIS® データ・プラットフォームによって使用される実際のメソッドです。これらのメソッドは、SQL 経由でデータにアクセスするときは使用されません。
密接に関連するトピックが、リテラル・プロパティに使用される "データ型クラスの定義" です。データ型クラスを定義する際には、このページで説明するように、プロパティ・メソッドをオーバーライドしなければならないことがあります。
プロパティ・メソッドを定義する方法
クラスにプロパティがある場合、クラス・コンパイラは各プロパティに多数のメソッドを自動的に生成し、それらを内部的に使用します。メソッドの名前は、プロパティ名に基づきます。
どのプロパティにも、2 つの場所からのロジックを使用する特別なメカニズムによって、プロパティ・メソッドが生成されます。
-
Get()、Set()、および確認コードなど、特定の組み込みプロパティの動作を提供する内部プロパティの動作クラス。プロパティの種類に応じて、さまざまな実装があります。リテラル・プロパティ、オブジェクト値プロパティ、コレクション・プロパティ、およびシリアル・オブジェクト・プロパティには、異なるプロパティ動作クラスがあります。これらは内部的なクラスであり、再定義することはできません。
-
プロパティによって使用されるデータ型クラスで定義されたメソッド (該当する場合)。これらのメソッドの多くは、メソッド・ジェネレータです。

プロパティ・ゲッター・メソッドのオーバーライド
プロパティのゲッター・メソッドをオーバーライドするには、そのプロパティを含むクラスを変更して、以下のようなメソッドを追加します。
-
PropertyNameGet という名前にする必要があります。PropertyName は、対応するプロパティの名前です。
-
引数を取りません。
-
返りタイプは、プロパティのタイプと同じにする必要があります。
-
プロパティの値を返す必要があります。
-
このプロパティの値を参照するには、このメソッドで変数 i%PropertyName を使用する必要があります。この名前では大文字と小文字が区別されます。
Important:特定のプロパティに対するこのゲッター・メソッド内では、そのプロパティの値を参照するために、..PropertyName 構文を使用してはいけません。そのようにすると、再帰的な参照の連続により <FRAMESTACK> エラーを招くことになります。ただし、その他のプロパティを参照する場合には ..PropertyName を使用できます。このようにしても、再帰が発生することがないためです。
変数 i%PropertyName はインスタンス変数です。インスタンス変数の詳細は、"i%PropertyName" を参照してください。
オブジェクトタイプ・プロパティまたは多次元プロパティのアクセサ・メソッドに対するオーバーライドはサポートされていません。また、メソッド名の最大長が 220 文字なので、長さが 218 文字、219 文字、または 220 文字の名前を持つプロパティのアクセサ・メソッドは作成できません。
以下に、HasValue という名前のプロパティ (タイプ %BooleanOpens in a new tab) のセッター・メソッドの例を示します。
Method HasValueGet() As %Boolean
{
If ((i%NodeType="element")||(i%NodeType="")) Quit 0
Quit 1
}
プロパティ・セッター・メソッドのオーバーライド
プロパティのセッター・メソッドをオーバーライドするには、そのプロパティを含むクラスを変更して、以下のようなメソッドを追加します。
-
PropertyNameSet という名前にする必要があります。PropertyName は、対応するプロパティの名前です。
-
1 つの引数を受け取ります。この引数にはプロパティの値を格納します。
具体的には、SET コマンドで指定された値です (プロパティが設定されている場合)。
-
%StatusOpens in a new tab 値を返す必要があります。
-
このプロパティの値を設定するには、このメソッドで変数 i%PropertyName を設定する必要があります。この名前では大文字と小文字が区別されます。
Important:特定のプロパティに対するこのセッター・メソッド内では、そのプロパティの値を参照するために、..PropertyName 構文を使用してはいけません。そのようにすると、再帰的な参照の連続により <FRAMESTACK> エラーを招くことになります。ただし、その他のプロパティを参照する場合には ..PropertyName を使用できます。このようにしても、再帰が発生することがないためです。
変数 i%PropertyName はインスタンス変数です。インスタンス変数の詳細は、"i%PropertyName" を参照してください。
オブジェクトタイプ・プロパティまたは多次元プロパティのアクセサ・メソッドに対するオーバーライドはサポートされていません。また、メソッド名の最大長が 220 文字なので、長さが 218 文字、219 文字、または 220 文字の名前を持つプロパティのアクセサ・メソッドは作成できません。
例えば、MyProp のタイプは %StringOpens in a new tab だとします。以下のセッター・メソッドを定義できます。
Method MyPropSet(value as %String) As %Status
{
if i%MyProp="abc" {
set i%MyProp="corrected value"
}
quit $$$OK
}
以下に示す別の例は、DefaultXmlns という名前のプロパティのセッター・メソッド (タイプ %StringOpens in a new tab) です。
Method DefaultXmlnsSet(value As %String) As %Status
{
set i%DefaultXmlns = value
If ..Namespaces'="" Set ..Namespaces.DefaultXmlns=value
quit $$$OK
}
この例では、同じオブジェクトの Namespaces プロパティを参照するために、..PropertyName 構文を使用しています。この使用法は、再帰が発生しないため、エラーになりません。
カスタム・アクセサ・メソッドによるオブジェクト値プロパティの定義
前述したように、オブジェクトタイプ・プロパティのアクセサ・メソッドに対するオーバーライドはサポートされていません。オブジェクト値を保持するプロパティを定義する必要があり、カスタム・アクセサ・メソッドを定義する必要もある場合は、%RawString. タイプでプロパティを定義します。これは、オブジェクト・クラスではなく汎用クラスであるため、このプロパティのアクセサ・メソッドはオーバーライドできます。このプロパティを使用する場合は、目的のクラスのインスタンスと等しくなるように設定します。
例えば、以下のクラスにはプロパティ Zip が含まれます。その公式の型は %RawStringOpens in a new tab です。プロパティの説明は、そのプロパティが Sample.USZipCode のインスタンスであることを示します。このクラスでは、ZipGet() および ZipSet() プロパティ・メソッドも定義されます。
Class PropMethods.Demo Extends %Persistent
{
/// Timestamp for viewing Zip
Property LastTimeZipViewed As %TimeStamp;
/// Timestamp for changing Zip
Property LastTimeZipChanged As %TimeStamp;
/// When setting this property, set it equal to instance of Sample.USZipCode.
/// The type is %RawString rather than Sample.USZipCode, so that it's possible
/// to override ZipGet() and ZipSet().
Property Zip As %RawString;
Method ZipGet() As %RawString [ ServerOnly = 1 ]
{
// get id, swizzle referenced object
set id = i%Zip
if (id '= "") {
set zip = ##class(Sample.USZipCode).%OpenId(id)
set ..LastTimeZipViewed = $zdt($zts)
}
else {
set zip = ""
}
return zip
}
Method ZipSet(zip As %RawString) As %Status [ ServerOnly = 1 ]
{
// set i% for new zip
if ($isobject(zip) && zip.%IsA("Sample.USZipCode")) {
set id = zip.%Id()
set i%Zip = id
set ..LastTimeZipChanged = $zdt($zts)
}
else {
set i%Zip = ""
}
quit $$$OK
}
}
以下のターミナル・セッションは、このクラスの使用法を示しています。
SAMPLES>set demo=##class(PropMethods.Demo).%New()
SAMPLES>write demo.LastTimeZipChanged
SAMPLES>set zip=##class(Sample.USZipCode).%OpenId(10001)
SAMPLES>set demo.Zip=zip
SAMPLES>w demo.LastTimeZipChanged
10/14/2015 19:21:08