検索
連載

大規模PHP開発で欠かせないアクセス修飾子とカプセル化、アクセサー、コンストラクター/デストラクターPHPオブジェクト指向プログラミング入門(2)(3/3 ページ)

「PHPで、どのようにオブジェクト指向プログラミングをしていくか」を解説する連載。今回は、アクセス修飾子、カプセル化と隠蔽(いんぺい)、アクセサー、コンストラクター/デストラクターについて解説し、最後に「再代入の是非」について触れます。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
前のページへ |       

コンストラクター/デストラクター

 インスタンスが作成されるときに自動的に走るメソッドとして「コンストラクター」というメソッドが、多くの言語に存在します。PHPにも、この「コンストラクター」が存在します。

 まずは実際にコードを書いて、コンストラクターの存在を確認してみます。

<?php
 
class hoge {
  public function __construct() {
    echo "run constructor\n";
  }
}
//
$obj = new hoge();

 __constructメソッドは、明示的には呼ばれていません。しかし「newされたタイミング」で自動で呼び出されます。その証左として、上述プログラムを動かすと「__constructメソッドをcallしていないのに、__constructメソッドが呼ばれている」様子が分かるかと思います。

 また、コンストラクターと対になる概念として「デストラクター」というメソッドがあります。デストラクターは言語によってあったりなかったりしますが(典型的には、Javaが「デストラクターのない」言語です)、PHPではデストラクターが存在します。

 デストラクターは「インスタンスが消去されるタイミング」で自動で呼び出されます。「消去されるタイミング」という状況を厳密に定義するのは少し難しいのですが、取りあえず「プログラム終了時」「変数のスコープが外れる」「インスタンスが入っている変数に別の値が代入される(典型的にはnullなどが代入される)」といったタイミングを意識しておくとよいでしょう。

 上述した三つのパターンのサンプルプログラムをそれぞれ書いて、デストラクターの存在、およびデストラクターが走るタイミングを確認してみます。

<?php
 
class hoge {
  public function __destruct() {
    echo "run destructor\n";
  }
}
// プログラム終了時にデストラクターが走る
$obj = new hoge();
<?php
 
class hoge {
  public function __destruct() {
    echo "run destructor\n";
  }
}
//
function f() {
  $obj = new hoge();
}
// 変数のスコープが外れる
f();
sleep(5); // 「プログラム終了時にデストラクターが走る」と区別するためのsleep
<?php
 
class hoge {
  public function __destruct() {
    echo "run destructor\n";
  }
}
// インスタンスが入っている変数に別の値が代入される
$obj = new hoge();
$obj = null;
sleep(5); // 「プログラム終了時にデストラクターが走る」と区別するためのsleep

 コンストラクターは、よく「インスタンスの初期化」などに用いられます。引数などで外部からデータを渡すことも可能です。エラーをreturnで返すことはできないので、「コンストラクターの処理でエラーになった」場合は、例外を投げる必要があります。

 デストラクターはあまり使われることがありませんが、主として「コンストラクターで確保したリソースの解放」などに用いられることが多いです。そういった意味合いでも「コンストラクターと対になる」ことが多いと言えます。

イミュータブル(immutable)なオブジェクトについての一考

 変数において「再代入の是非」というのが今でも議論されています。「再代入」というのは簡単に書くと「一度変数に何か値をいれた後で、別の値を上書きする」ことです。

<?php
 
$i = 10;
var_dump($i);
$i = 20; // ここで変数$iに、値を再代入
var_dump($i);

 こういった「再代入」は、関数型言語、と呼ばれる言語の世界観では「できない(あるいは好ましくない)」とされています。

 この「再代入の禁止」というのは、手続き型言語の一つであるPHPを「普通に」学んでいると、「全面的に取り入れる」のは難しいと思いますが、クラスの設計によっては「一度入れられた値を変える必要がない(または変えるとバグが発生しやすくなる)」もの、ということがあり得ます。

 そういったときに「コンストラクターで値を設定、その後に値を変えることができない」クラス、というパターンが有効な場合があり、それを「イミュータブルなオブジェクト(不変オブジェクト)」という言い方をします。

 実装例を書いてみましょう。

<?php
 
class hoge {
  public function __construct($v) {
    $this->_val = $v;
  }
  public function getVal() {
    return $this->_val;
  }
//
private $_val;
}
//
$obj = new hoge('vall');
var_dump( $obj->getVal() );

 イミュータブルなオブジェクトでは、コンストラクターでデータを決定させます。また、setterは作成しません。プロパティはもちろんprivateになります。

 イミュータブルなインスタンスは「再代入がない」ので、結果的に「そのインスタンスがどんな情報を持っているか」が明示的であり、「プログラムの流れによってインスタンスの状態が遷移する可能性がない」と言えます。

 また、その状況は結果的に「デバッグの容易性」「テストパターンの減少」など、いくつかのメリットを生じさせます。本連載のメインターゲットである「初級本を読み終わった/PHP 5技術者認定初級試験には合格した」くらいの人だと、まだ少し難しい概念ですが、今は「そんなものもあるんだ」といった程度に覚えておいてください。

 こういったさまざまな概念を状況に合わせて使いこなせるようになると、プログラミングの腕前が上がって、より良いコードが書けるようになります。

次回は「継承」について

 次回は、オブジェクト指向プログラミングの中でも一つ大きなポイントになる「継承」について、書き方と考え方の両方向から解説していきます。

筆者紹介

古庄道明

1970年浅草生まれ。1995年に富士通系のソフトハウスに就職しプログラマーに転身。1999年個人事業主として独立し現在に至る。「寺子屋」「格子組」といったエンジニア支援活動を独自に展開し、占い師時代の「ガルーダ」という占い師名にちなんだ「がる先生」の愛称で親しまれている。

コンサルティングからシステム設計、ネットワークにセキュリティと、守備範囲は比較的多岐にわたる。「技術の基本は、その技術がないときの“困ってる”が根っこ」をモットーに、古い話から現代へ歴史をたどるように教えるのが持ち味。


Copyright © ITmedia, Inc. All Rights Reserved.

前のページへ |       
ページトップに戻る