Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】CachingIterator::__construct()メソッドの使い方

__constructメソッドの使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

__constructメソッドは、CachingIteratorクラスの新しいインスタンスを生成する際に呼び出されるメソッドです。このメソッドは、内部でキャッシュするための元となるイテレータオブジェクトを引数として受け取り、インスタンスの初期化を実行します。第一引数には、ArrayIteratorのようなIteratorインターフェースを実装したオブジェクトを指定します。CachingIteratorは、この渡されたイテレータを内部で保持し、要素を一つずつ取り出す際にキャッシュする機能を提供します。これにより、hasNext()メソッドを用いて、現在の要素を処理している段階で次の要素が存在するかどうかを事前に確認することが可能になります。この機能は、例えばリストの最後の要素だけ異なる処理を加えたい場合に特に有効です。また、オプションの第二引数としてフラグを指定することで、動作を細かく制御することも可能です。代表的なフラグであるCachingIterator::FULL_CACHEを使用すると、全ての要素が内部にキャッシュされ、一度完了したイテレーションを再度やり直すことができます。このように、__constructメソッドは、既存のイテレータにキャッシュ機能を追加するための準備を行う、このクラスの基本的な入り口となります。

構文(syntax)

1public CachingIterator::__construct(Iterator $iterator, int $flags = CachingIterator::CALL_TOSTRING)

引数(parameters)

Iterator $iterator, int $flags = 1

  • Iterator $iterator: 処理対象となるイテレータ
  • int $flags = 1: 挙動を制御するフラグ (デフォルトは1)

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP 8 コンストラクタプロパティプロモーションでイテレータを扱う

1<?php
2
3declare(strict_types=1);
4
5/**
6 * CachingIteratorのコンストラクタを模倣し、
7 * PHP 8の「コンストラクタプロパティプロモーション」を説明するクラス。
8 *
9 * このクラスはIteratorAggregateインターフェースを実装しているため、
10 * foreachループで直接使用できます。
11 */
12class MyCachingIterator implements IteratorAggregate
13{
14    // PHP 8の「コンストラクタプロパティプロモーション」機能を使用しています。
15    // コンストラクタの引数に `private` のような可視性を宣言するだけで、
16    // 自動的に同名のプロパティがクラスに定義され、引数の値が代入されます。
17    // これにより、プロパティの宣言とコンストラクタ内での `$this->... = ...` という
18    // 定型的な代入コードを省略でき、クラス定義が非常に簡潔になります。
19    public function __construct(
20        private Iterator $iterator,
21        private int $flags = CachingIterator::CALL_TOSTRING // デフォルト値は1
22    ) {
23    }
24
25    /**
26     * 内部に保持しているイテレータを返します。
27     * これにより、このクラスのインスタンスをforeachで利用できます。
28     */
29    public function getIterator(): Traversable
30    {
31        // コンストラクタでプロパティとして自動的に設定された$this->iteratorを返します。
32        return $this->iterator;
33    }
34
35    /**
36     * コンストラクタで設定されたフラグの値を取得します。
37     */
38    public function getFlags(): int
39    {
40        return $this->flags;
41    }
42}
43
44// 1. テスト用のデータを持つイテレータを作成します。
45$colors = new ArrayIterator(['Red', 'Green', 'Blue']);
46
47// 2. コンストラクタプロパティプロモーションを使用したクラスをインスタンス化します。
48//    $colorsが$iterator引数に渡され、自動的に privateプロパティ $iterator に格納されます。
49$myIterator = new MyCachingIterator($colors);
50
51// 3. foreachでクラスのインスタンスをループ処理します。
52//    getIterator()メソッドが内部のArrayIteratorを返すため、正しく動作します。
53echo "カラーリスト:" . PHP_EOL;
54foreach ($myIterator as $key => $color) {
55    echo "  {$key}: {$color}" . PHP_EOL;
56}
57
58// 4. プロパティが正しく設定されていることを確認します。
59echo PHP_EOL;
60echo "設定されたフラグの値: " . $myIterator->getFlags() . PHP_EOL;
61
62?>

CachingIteratorクラスのコンストラクタ__constructは、新しいインスタンスを作成する際に呼び出される特別なメソッドです。

第一引数$iteratorには、繰り返し処理の対象となるIteratorオブジェクトを指定します。第二引数の$flagsは、イテレータの動作を制御するためのオプションのフラグで、省略した場合はデフォルト値が使用されます。コンストラクタのため、このメソッド自体に戻り値はありません。

サンプルコードのMyCachingIteratorクラスでは、PHP 8の新機能「コンストラクタプロパティプロモーション」が利用されています。これは、コンストラクタの引数にprivateのようなアクセス修飾子を記述するだけで、クラスに同名のプロパティが自動的に宣言され、渡された引数の値がそのプロパティに代入される機能です。

この機能により、従来は別途記述する必要があったプロパティ宣言と、コンストラクタ内での代入処理($this->プロパティ = $引数;)を省略でき、コードが非常に簡潔になります。サンプルでは、$colorsオブジェクトがコンストラクタに渡されると、自動的にprivate$iteratorプロパティに格納されていることがわかります。

サンプルコードで利用されている「コンストラクタプロパティプロモーション」は、PHP 8.0から導入された機能です。そのため、古いバージョンのPHP環境では構文エラーとなりますので注意が必要です。この機能は、コンストラクタの引数にpublicprotectedprivateのいずれかの可視性を付けることで、プロパティの宣言と初期化を同時に行うものです。可視性を付け忘れると、プロパティは自動作成されず、単なるローカル変数として扱われます。この構文はコンストラクタ(__constructメソッド)専用であり、他のメソッドでは利用できません。コードが簡潔になる一方で、プロパティの定義箇所が分かりにくくなる場合があるため、チーム開発では規約を確認することが重要です。

PHP CachingIterator::constructを継承する

1<?php
2
3/**
4 * CachingIteratorを継承し、親クラスのコンストラクタを呼び出すサンプルクラス
5 *
6 * このクラスは、親であるCachingIteratorの機能を拡張する例を示します。
7 * 子クラスのコンストラクタ内で parent::__construct() を呼び出すことで、
8 * 親クラスの初期化処理を確実に実行しています。
9 */
10class ExtendedCachingIterator extends CachingIterator
11{
12    /**
13     * コンストラクタ
14     *
15     * 受け取った引数をそのまま親クラス(CachingIterator)のコンストラクタに渡します。
16     * これにより、CachingIteratorとしての基本的な機能が利用可能になります。
17     *
18     * @param Iterator $iterator ラップするイテレータオブジェクト
19     * @param int $flags 動作を制御するフラグ (デフォルトはCALL_TOSTRING)
20     */
21    public function __construct(Iterator $iterator, int $flags = self::CALL_TOSTRING)
22    {
23        // 'parent'キーワードを使い、親クラスであるCachingIteratorのコンストラクタを呼び出す
24        parent::__construct($iterator, $flags);
25        echo "ExtendedCachingIterator is initialized." . PHP_EOL;
26    }
27
28    /**
29     * 現在の要素が最後の要素かどうかを文字列で返すカスタムメソッド
30     *
31     * @return string
32     */
33    public function isLastElement(): string
34    {
35        // 親クラスが提供する hasNext() メソッドを利用して判定
36        return $this->hasNext() ? 'No' : 'Yes';
37    }
38}
39
40// 1. イテレータとして利用する元データを作成
41$fruits = ['Apple', 'Banana', 'Cherry'];
42$arrayIterator = new ArrayIterator($fruits);
43
44// 2. CachingIteratorを継承したカスタムクラスのインスタンスを生成
45// このとき、ExtendedCachingIteratorの__constructが呼ばれ、
46// その中で親であるCachingIteratorの__constructも呼び出される
47$iterator = new ExtendedCachingIterator($arrayIterator);
48
49echo "--- Start Loop ---" . PHP_EOL;
50
51// 3. ループ処理で結果を確認
52// CachingIteratorの機能と、追加したカスタムメソッドの両方が使える
53foreach ($iterator as $key => $value) {
54    echo "[{$key}] Value: {$value}, Is Last? " . $iterator->isLastElement() . PHP_EOL;
55}
56
57echo "--- End Loop ---" . PHP_EOL;
58
59?>

このサンプルコードは、CachingIteratorクラスを継承し、そのコンストラクタ__construct()を呼び出す方法を示しています。

CachingIterator::__constructは、新しいCachingIteratorオブジェクトを生成するためのコンストラクタです。このメソッドは、引数で受け取ったイテレータを内部に保持し、次の要素を先読み(キャッシュ)する機能を提供します。

コード内のExtendedCachingIteratorクラスでは、自身のコンストラクタ内でparent::__construct()という記述を用いています。parentキーワードは親クラス(この場合はCachingIterator)を指し、parent::__construct()で親クラスのコンストラクタを呼び出しています。これにより、CachingIteratorが持つ本来の初期化処理が実行され、その機能を正しく引き継ぐことができます。

第1引数$iteratorには、ArrayIteratorなどの元となるイテレータオブジェクトを渡します。第2引数$flagsは、イテレータの挙動を制御するためのオプションのフラグです。コンストラクタであるため、特定の戻り値はなく、オブジェクトのインスタンスを初期化する役割を担います。このように親のコンストラクタを呼び出すことで、親が持つメソッド(例: hasNext())を利用しつつ、独自の機能を追加したクラスを作成できます。

子クラスでコンストラクタを定義する場合、親クラスのコンストラクタは自動では呼び出されません。そのため、parent::__construct()を使って明示的に親クラスの初期化処理を呼び出すことが重要です。これを忘れると、親クラスの機能が正しく準備されず、メソッドが期待通りに動作しない原因となります。このサンプルコードのように、親のコンストラクタが必要とする引数を正しく渡す必要もあります。親の初期化を先に行うため、通常は子クラスのコンストラクタの最初にparent::__construct()を記述するのが安全です。このように、継承したクラスの機能を確実に利用するためには、親クラスの初期化を正しく行うことが不可欠です。

関連コンテンツ