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?

プロパティ・メソッドの使用とオーバーライド

この章では、プロパティ・メソッドについて説明します。プロパティ・メソッドは OREF を使用してオブジェクトのプロパティを操作するときに、Caché によって使用される実際のメソッドです。以下のトピックについて説明します。

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

プロパティ・メソッドの概要

プロパティには、自動的に関連付けられた多くのメソッドがあります。これらのメソッドは、標準の継承を介して継承されません。その代わりに、各プロパティに対する一連のメソッドを作成するために、特別なプロパティの振る舞いメカニズムを使用します。

各プロパティは、2 つの場所からの一連のメソッドを継承します。

  • Get()Set()、および確認コードなど、組み込みの動作を提供する %Property クラス。

  • プロパティによって使用されるデータ型クラス (該当する場合)。これらのメソッドの多くは、メソッド・ジェネレータです。

プロパティの振る舞い
generated description: propertybehavior

プロパティの振る舞いクラスは、システム・クラスです。プロパティの振る舞いは、指定、または修正できません。

例えば、3 つのプロパティでクラス Person を定義する場合、以下のようになります。

Class MyApp.Person Extends %Persistent
{
Property Name As %String;
Property Age As %Integer;
Property DOB As %Date;
}

コンパイルされた Person クラスは、各プロパティに対して自動的に生成された一連のメソッドを持ちます。これらのメソッドは、プロパティと関連するデータ型クラスからも、システムの Property クラスからも継承されます。生成されたこれらのメソッド名は、プロパティ名に継承クラスからのメソッド名を連結した名前です。例えば、DOB プロパティに関連付けられたメソッドでは以下のようになります。

 Set x = person.DOBIsValid(person.DOB)
 Write person.DOBLogicalToDisplay(person.DOB)

IsValid() はプロパティ・クラスのメソッドで、LogicalToDisplay()%DateOpens in a new tab データ型クラスのメソッドです。

リテラル・プロパティのプロパティ・アクセサ

オブジェクト・プロパティを参照する Caché のドット構文は、値を取得および設定するアクセサ・メソッドのセットへのインターフェイスです。それぞれの非計算プロパティについては、コードから oref.Prop (oref はオブジェクト、Prop はプロパティ) を参照すると、常にシステム提供の PropGet() メソッド、または PropSet() メソッドが呼び出されたかのように実行されます。以下に例を示します。

 Set person.DOB = x

上記のコードは、以下のメソッドが呼び出されたかのように振る舞います。

 Do person.DOBSet(x)

以下のコードは、

 Write person.Name

以下のように振る舞います。

 Write person.NameGet()

多くの場合、実際には PropGet() メソッドや PropSet() メソッドは存在しません。最善のパフォーマンスを得るために、単純なプロパティへのアクセスは Caché 仮想マシン内で直接実装されます。ただし、プロパティがオブジェクトタイプまたは多次元でない限り、特定のプロパティのために PropGet() メソッドと PropSet() メソッドを用意できます。これらのメソッドを定義すると、そのメソッドは実行時に、システムによって自動的に呼び出されます。以下のセクションでは、これらのアクセッサ・メソッドを定義する方法を説明します。カスタム・メソッド内では、アプリケーションに必要な任意の特別な処理を実行できます。

スタジオの [新規プロパティ・ウィザード] の最後の画面には、カスタム Get() メソッド、Set() メソッド、またはその両方を生成するオプションが用意されています。これらのオプションを使用すると、スタジオは適切なシグニチャと共にスタブ・メソッドを定義します。

オブジェクト値プロパティのプロパティ・アクセサ

すべての参照プロパティに対しては、SetObject() (OID 値を使用する) メソッドと SetObjectId() (ID 値を使用する) メソッドがあります。例えば、特定の保存された Person オブジェクトを Car オブジェクトの持ち主として割り当てるには、以下のコードを使用します。

 Do car.OwnerSetObjectId(PersonId)

carCar オブジェクトの OREF、PersonId は保存された Person オブジェクトの ID です。

GetObject() メソッドと GetObjectId() メソッドも使用できます。これらのメソッドは、それぞれ参照プロパティに関連付けられている OID または ID を取得します。まとめると、以下のメソッドがあります。

  • GetObject() — プロパティに関連付けられている OID を取得します。プロパティの名前が prop の場合、メソッド名は propGetObject() です。

  • GetObjectId() — プロパティに関連付けられている ID を取得します。プロパティの名前が prop の場合、メソッド名は propGetObjectId() です。

  • SetObject() — プロパティに関連付けられている OID を設定します。プロパティの名前が prop の場合、メソッド名は propSetObject() です。

  • SetObjectId() — プロパティに関連付けられている ID を設定します。プロパティの名前が prop の場合、メソッド名は propSetObjectId() です。

プロパティ・ゲッター・メソッドのオーバーライド

プロパティのゲッター・メソッドをオーバーライドするには、そのプロパティを含むクラスを変更して、以下のようなメソッドを追加します。

  • PropertyNameGet という名前にする必要があります。PropertyName は、対応するプロパティの名前です。

  • 引数を取りません。

  • 返りタイプは、プロパティのタイプと同じにする必要があります。

  • プロパティの値を返す必要があります。

  • このプロパティの値を参照するには、このメソッドで変数 i%PropertyName を使用する必要があります。この名前では大文字と小文字が区別されます。

    Important:

    特定のプロパティに対するこのゲッター・メソッド内では、そのプロパティの値を参照するために、..PropertyName 構文を使用してはいけません。そのようにすると、再帰的な参照の連続により <FRAMESTACK> エラーを招くことになります。ただし、その他のプロパティを参照する場合には ..PropertyName を使用できます。このようにしても、再帰が発生することがないためです。

    変数 i%PropertyNameインスタンス変数です。インスタンス変数の詳細は、“登録オブジェクトを使用した作業” の章の “i%PropertyName” を参照してください。

Note:

オブジェクトタイプ・プロパティまたは多次元プロパティのアクセサ・メソッドに対するオーバーライドはサポートされていません。また、メソッド名の最大長が 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” を参照してください。

Note:

オブジェクトタイプ・プロパティまたは多次元プロパティのアクセサ・メソッドに対するオーバーライドはサポートされていません。また、メソッド名の最大長が 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 構文を使用しています。この使用法は、再帰が発生しないため、エラーになりません。

カスタム・アクセサ・メソッドによるオブジェクト値プロパティの定義

前述したように、オブジェクトタイプ・プロパティのアクセサ・メソッドに対するオーバーライドはサポートされていません。オブジェクト値を保持するプロパティを定義する必要があり、カスタム・アクセサ・メソッドを定義する必要もある場合は、%CacheString タイプでプロパティを定義します。これは、オブジェクト・クラスではなく汎用クラスであるため、このプロパティのアクセサ・メソッドはオーバーライドできます。このプロパティを使用する場合は、目的のクラスのインスタンスと等しくなるように設定します。

例えば、以下のクラスにはプロパティ Zip が含まれます。その公式の型は %CacheString です。プロパティの説明は、そのプロパティが Sample.USZipCodeOpens in a new tab のインスタンスであることを示します。このクラスでは、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 %CacheString rather than Sample.USZipCode, so that it's possible 
/// to override ZipGet() and ZipSet().
Property Zip As %CacheString;

Method ZipGet() As %CacheString [ 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 %CacheString) 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
FeedbackOpens in a new tab