For PHP5 applications, the all of the "aggregate" function family is now in runkit.
http://php.net/manual/en/ref.runkit.php
CI. オブジェクトの集約/合成関数
| 警告 |
この拡張モジュールは、 実験的 なものです。この拡張モジュールの動作・ 関数名・その他ドキュメントに書かれている事項は、予告なく、将来的な PHP のリリースにおいて変更される可能性があります。 このモジュールは自己責任で使用してください。 |
導入
オブジェクト指向プログラミングでは、簡単なクラス (または インスタンス) を組み合わせてより複雑なクラスを作成するということが 一般に行われます。これは、複雑なオブジェクトやオブジェクト階層を 構築するための柔軟な方法であり、多重継承と同等のことを動的に行う 機能を有します。 クラス(またはオブジェクト)を合成するには、合成される要素の間の 関係により関連(Association)と 集約(Aggregation)の 2 種類の方法があります。
関連は、独立に構築され、外部から 可視の部分を合成したものです。クラスまたはオブジェクトを 関連づける場合、各クラスは関連するクラスへのリファレンスを保持します。 複数のクラスを静的に関連づける場合は、クラスは他のクラスの インスタンスへのリファレンスを含みます。例えば、
例 2. オブジェクトの関連
|
一方、集約では、合成されたパーツのカプセル化 (隠蔽) が行われます。(静的な) 内部クラス (PHP はまだ内部クラスを サポートしていません) を使用することにより、クラスを集約することが できます。この場合、このクラスを含むクラスを通じる場合以外、集約された クラスの定義にはアクセスできません。複数のインスタンスの集約 (オブジェクト集約) は、あるオブジェクトの内部にサブオブジェクトを 動的に作成することを意味し、この過程でこのオブジェクトのプロパティと メソッドを拡張します。
オブジェクトの集約は、(例えば、分子は原子を集約したものであるといった) 包含関係を表す際の自然な方法であり、サブクラスを複数の親クラス およびそのインターフェイスに永続的にバインドすることなく、 多重継承と等価な機能を得るために使用できます。 実際、オブジェクトの集約はより柔軟に使用することができ、集約される オブジェクトで継承するメソッドまたはプロパティを選択することが できます。
例
3 つのクラスを定義し、各々に別々のストレージメソッドを実装します。
例 3. storage_classes.inc
|
この定義済みクラスを用いていくつかのオブジェクトをインスタンス化し、 集約や集約の解除を行いつつ随時オブジェクトの情報を出力します。
例 4. test_aggregation.php
|
出力内容を見ながら、PHP の集約についての副作用や制限事項を 考えてみましょう。 まず、新しく作成されたオブジェクト $fs および $ws は、期待通りの (対応するクラス定義に もとづく) 結果を出力します。 PHP では実際のところクラス/オブジェクトの要素についてパブリック/ プライベートの区別はありませんが、集約の際には クラス/オブジェクトのプライベート要素はアンダースコア文字 ("_") で始まるとみなします。
$fs オブジェクト
クラス: filestorage
プロパティ: data (array)
0 => 3.1415926535898
1 => kludge != cruft
メソッド: filestorage
メソッド: write
$ws オブジェクト
クラス: wddxstorage
プロパティ: data (array)
0 => 3.1415926535898
1 => kludge != cruft
プロパティ: version = 1.0
プロパティ: _id = ID::9bb2b640764d4370eb04808af8b076a5
メソッド: wddxstorage
メソッド: store
メソッド: _genid |
次に $fs を WDDXStorage クラスと集約し、オブジェクトの情報を出力します。 $fs は今でも FileStorage のままですが、プロパティ $version およびメソッド store() が存在することがわかるでしょう。これらは いずれも WDDXStorage で定義されているものです。 注意すべき点は、クラスで定義されているプライベート要素は集約されていない ということです。それらは $ws オブジェクトの中には 存在します。また、WDDXStorage のコンストラクタも 存在しません。これを集約するのは論理的ではありません。
$fs を WDDXStorage クラスに集約します
$fs オブジェクト
クラス: filestorage
プロパティ: data (array)
0 => 3.1415926535898
1 => kludge != cruft
プロパティ: version = 1.0
メソッド: filestorage
メソッド: write
メソッド: store |
集約処理は、積み重ねていくことが可能です。そこで今度は $fs と DBStorage を 集約します。これにより、定義されているすべてのクラスの 保存処理メソッドを使用可能なオブジェクトができあがります。
それを DBStorage クラスに集約します
$fs オブジェクト
クラス: filestorage
プロパティ: data (array)
0 => 3.1415926535898
1 => kludge != cruft
プロパティ: version = 1.0
プロパティ: dbtype = mysql
メソッド: filestorage
メソッド: write
メソッド: store
メソッド: save |
最後に、プロパティやメソッドを動的に集約したのと同じ方法で、 集約したプロパティやメソッドを解除することも可能です。 $fs から WDDXStorage クラスの集約を解除すると、このような結果になります。
WDDXStorage を集約から解除します
$fs オブジェクト
クラス: filestorage
プロパティ: data (array)
0 => 3.1415926535898
1 => kludge != cruft
プロパティ: dbtype = mysql
メソッド: filestorage
メソッド: write
メソッド: save |
上で説明しきれなかったことがひとつあります。それは、集約処理の際には 既存のプロパティやメソッドは上書きされないということです。例えば、 FileStorage クラスでは $data というプロパティを定義しており、 WDDXStorage クラスでも同名のプロパティが 定義されていますが、このプロパティが FileStorage のインスタンス化の際に 取得したプロパティの内容を上書きすることはありません。
- 目次
- aggregate_info -- オブジェクトに集約された各クラスのメソッドとプロパティを 連想配列で返す
- aggregate_methods_by_list -- 選択したクラスメソッドを、動的にオブジェクトに集約する
- aggregate_methods_by_regexp -- 正規表現を使用して選択したクラスメソッドを、 動的にオブジェクトに集約する
- aggregate_methods -- クラスのメソッドを、動的にオブジェクトに集約する
- aggregate_properties_by_list -- 選択したクラスプロパティを、動的にオブジェクトに集約する
- aggregate_properties_by_regexp -- 正規表現を使用して選択したクラスプロパティを、 動的にオブジェクトに集約する
- aggregate_properties -- クラスのプロパティを、動的にオブジェクトに集約する
- aggregate -- メソッドおよびプロパティの動的なクラス/オブジェクト集約を行う
- aggregation_info -- aggregate_info() のエイリアス
- deaggregate -- 集約されたメソッドやプロパティをオブジェクトから取り除く
It is worth noting that class association does not work, even in PHP 4.3.0 - this ability is experimental. I'm assuming it was added in for the sake of forwards-compatibilty. Use object association instead for now.
Until it is implemented, you will receieve a parse error when attempting to use it.
Related bug report: http://bugs.php.net/bug.php?id=20531
Just to prevent people posting about "why it doesn't work??", etc etc etc.
If you need to serialize an object for sessions or other purposes, and want to save aggregation state, extend it from a base class such as this one, and use $this->agg/$this->unagg instead of aggregate/deaggregate
<?php
class base
{
var $_aggregates = array();
function agg($agg)
{
aggregate($this,$agg);
$this->_aggregates[$agg] = 1;
}
function unagg($agg = false)
{
if ($agg)
{
deaggregate($this,$agg);
unset($this->_aggregates[$agg]);
} else
{
deaggregate($this);
$this->_aggregates = array();
}
}
}
?>
