Foundation > IlvNamedProperty:永続性プロパティー・クラス > 名前付きプロパティーの拡張
 
名前付きプロパティーの拡張
独自の名前付きプロパティー・クラスを作成するのは簡単で、次の 3 つの手順に従います。
1. IlvNamedProperty のサブクラスを作成します。
2. このプロパティーにアクセスするシンボルを作成します。
Rogue Wave Views では、「_ilv」で名前が始まるシンボルはすべて内部用に予約されています。
3. このクラスの永続性を定義し、Rogue Wave Views へ登録します。
次のセクションでは、2 つの値を格納する非常に簡単な例を使用して、グラフィック・オブジェクトと関連付けられる名前付きプロパティーの作成方法を説明します。ただし、メンバー関数を使用して名前付きプロパティーを作成してより複雑なデータ・メンバーを処理したり、既存クラスへのポインターを格納する名前付きプロパティーを作ったりすることもできます。名前付きプロパティーを使用すると、必要最小限のコーディングで、アプリケーション・クラスの API を変更することなく、複雑なアプリケーション・データを軽量なグラフィック・オブジェクトにリンクできます。
例:名前付きプロパティーの作成
ここでは整数と文字列の両方を含む名前付きプロパティーを作成し、それを簡単にアクセス可能にし、永続性を持たせます。
一般的な操作は次のとおりです。
*名前付きプロパティーの宣言:ヘッダー・ファイル
*名前付きプロパティーにアクセスするシンボルの定義
*名前付きプロパティーのコンストラクターを定義する
*setString メンバー関数の定義
*永続性およびコピー・コンストラクターの定義
*write メンバー関数の定義
*読み込み/コピー・コンストラクターへのエントリー・ポイントを提供する
*クラスの登録
*新規名前付きプロパティーの使用
名前付きプロパティーの宣言:ヘッダー・ファイル
ここで作成する名前付きプロパティーは、IlvNamedProperty のサブクラスである必要があります。名前付きプロパティーは整数と文字列を格納します。完全なヘッダー・ファイルは以下のとおりです。
#include <ilviews/base/graphic.h>
 
class MyProperty
: public IlvNamedProperty
{
public:
MyProperty(int integer,
char* string);
virtual ~MyProperty();
 
int getInteger() const { return _integer; }
void setInteger(int integer) { _integer = integer; }
 
const char* getString() const { return _string; }
void setString(const char* string);
 
static IlSymbol* GetSymbol();
 
DeclarePropertyInfo();
DeclarePropertyIOConstructors(MyProperty);
 
private:
int _integer;
char* _string;
static IlSymbol* _Symbol;
};
2 つのデータ・メンバー _integer_string (およびそのアクセサー) の他に、_Symbol スタティック・データ・メンバーおよびクラスの宣言部分に表示される
2 つのマクロ DeclarePropertyInfoDeclarePropertyIOConstructors に焦点を当てます。
クラスのデストラクターは、IlvNamedProperty ベース・クラスの 1 つと同様、仮想のものです。
名前付きプロパティーにアクセスするシンボルの定義
まず、このクラスへのアクセスに使用するシンボルを定義します。このシンボルを簡単に定義するには、シンボルをプロパティー・クラス _Symbol のスタティック・データ・メンバーにし、パブリック・アクセサー GetSymbol を提供します。これにより、インスタンスとオブジェクトの関連付けに使用するシンボルを認識する必要なく、どのアプリケーションでも MyProperty のインスタンスでも取得できるようになります。
パブリックおよびスタティック・アクセサーの GetSymbol は、適切な IlSymbol を返し、必要に応じてそれを作成するように定義付けられます。
下記のコードは実装ファイルからの抽出であり、プロパティー・シンボルのアクセサーと 0 に初期化するスタティック・データ・メンバーの両方を定義します。シンボルは MyProperty::GetSymbol で最初に問い合わせを行うときに作成されます。
IlSymbol*
MyProperty::GetSymbol()
{
if (!_Symbol)
_Symbol = IlGetSymbol("MyPropertySymbol");
return _Symbol;
}
 
IlSymbol* MyProperty::_Symbol = 0;
名前付きプロパティーのコンストラクターを定義する
ここでは、コンストラクターとデストラクターを扱います。ここで必要なのは、親クラスである IlvNamedProperty のコンストラクターを呼び出し、データ・メンバーを初期化することです。
MyProperty::MyProperty(int integer,
char* string)
: IlvNamedProperty(GetSymbol()),
_integer(integer),
_string(0)
{
setString(string);
}
 
MyProperty::~MyProperty()
{
if (_string)
delete [] _string;
}
最初に MyProperty タイプのプロパティーを作成する際に、スタティック・メンバー関数である GetSymbol が呼び出され、スタティック・データ・メンバー _Symbol を有効値に設定します。
setString メンバー関数によって string パラメーターがコピーされ、_string データ・メンバーが有効であるかどうかチェックされます。このために、このデータ・メンバーをコンストラクターの初期化指定子で 0 に初期化することが必要です。このパラメーターは、有効である場合、デストラクターによって破壊されます。
setString メンバー関数の定義
下記は文字列をコピー、格納する setString メンバー関数の定義です。
void
MyProperty::setString(const char* string)
{
if (_string)
delete [] _string;
_string = string
? strcpy(new char [strlen(string)+1], string)
: 0;
}
このコードは非常に簡単です。有効な文字列、つまり非ヌル文字列が格納された場合、文字列は破壊されます。パラメーターが有効、つまり非ヌルの場合、この文字列がコピーされ、格納されます。パラメーターが有効でない場合、データ・メンバーは単に 0 にリセットされます。
この段階で、この例のクラスは整数と文字列値の両方を格納、取得できます。
永続性およびコピー・コンストラクターの定義
この例で名前付きプロパティーを完成させるには、クラス・レベルの情報と永続性に関連するメンバー関数を追加する必要があります。これをもっとも簡単に行うには、次の 2 つのマクロをクラス宣言の本文に使用します。
*DeclarePropertyInfo は、MyProperty クラスのクラス情報データ・メンバーを宣言します。これらのメンバーは、クラス名やその階層などの情報を取得するために使用します。これはまた、このクラスの永続性実装に必要なメンバー関数も宣言します。
*DeclarePropertyIOConstructors は、永続性およびコピーに必要なコンストラクターを宣言します。
これらのマクロにより、クラスにコピー機能および永続性機能を非常に簡単に追加できます。
メンバー関数を宣言したら、コピーおよび永続性機能をクラスに追加するために、コピー・コンストラクターとパラメーターとして IlvInputFile を参照するコンストラクターを定義します。
MyProperty::MyProperty(const MyProperty& source)
: IlvNamedProperty(GetSymbol()),
_integer(source._integer),
_string(0)
{
setString(source._string);
}
 
MyProperty::MyProperty(IlvInputFile& i, IlSymbol* s)
: IlvNamedProperty(GetSymbol()),
_integer(0),
_string(0)
{
// 's' should be equal to GetSymbol()
i.getStream() >> _integer >> IlvQuotedString();
setString(IlvQuotedString().Buffer);
}
最初のコンストラクターはそのソース・パラメーターのコピーで MyProperty の新しいインスタンスを初期化します。
2 つ目のコンストラクターは、提供された入力ストリームを読み込んで、そのインスタンスを読み込まれたもので初期化します。
write メンバー関数の定義
これでクラスの新しいインスタンスを読み込み、保存できます。このためには、write メンバー関数を定義します。これは暗示的に DeclarePropertyInfo マクロで宣言されます。
void
MyProperty::write(IlvOutputFile& o) const
{
    o.getStream() << _integer << IlvSpc() << IlvQuotedString(_string);
}
保存順は読み込み順と同じになります。
保存する追加情報がない名前付きプロパティーを定義する場合もあります。この場合は、クラス宣言で DeclarePropertyInfo ではなく DeclarePropertyInfoRO マクロを使用して、無効になる write メンバー関数を削除します。
読み込み/コピー・コンストラクターへのエントリー・ポイントを提供する
Rogue Wave Views に読み込みおよびコピー・コンストラクターへのエントリー・ポイントを提供するには、別のマクロを実装ファイルに追加する必要があります。これは次のように、関数の本文外で行います。
IlvPredefinedPropertyIOMembers(MyProperty)
このマクロを呼び出すと実際に、読み込みコンストラクターを呼び出す read スタティック・メンバー関数が作成されます。これはまた、コピー・コンストラクターを呼び出す copy メンバー関数の定義も行います。
クラスの登録
名前付きプロパティーをアプリケーションで実行する最終手順として、以下のように MyProperty クラスを Rogue Wave Views に登録します。
IlvRegisterPropertyClass(MyProperty, IlvNamedProperty);
IlvRegisterPropertyClass マクロの呼び出しにより、MyProperty クラスを Rogue Wave Views の永続性メカニズムに登録します。
新規名前付きプロパティーの使用
これでこの新しい名前付きプロパティーを、関連付けられるあらゆるグラフィック・オブジェクトの拡張として使用できます。
IlvGraphic* myObject = ...;
myObject->setNamedProperty(new MyProperty(12, "Some text"));
...
MyProperty* property =
          (MyProperty*)(myObject->getNamedProperty(MyProperty::GetSymbol());
if (property && (property->getInteger() == someValue))
    doSomething();
グラフィック・オブジェクトの API が、ベース・クラスをサブクラス化をすることなく永続的に拡張されました。

Version 6.0
Copyright © 2015, Rogue Wave Software, Inc. All Rights Reserved.