PHP - OOP - 10. Exceptionクラスの継承
引き続き継承について学習していきましょう。ここでは Exception
クラスを継承して例外クラスの作成に取り組みます。
Exceptionクラスの継承
これまでに学習してきたようにPHPには例外を表す Exception
クラスが用意されています。この Exception
クラスを継承して独自の例外クラスを定義できます。次のプログラムを MyException.php
ファイルとして作成してみましょう。
<?php
class MyException extends Exception
{
}
ここでは MyException
という名前で例外クラスを定義しています。クラスの中では新たなプロパティやメソッドを追加していませんが、このようなプログラムも問題なく動作します。 MyException
クラスも Exception
型のインスタンスと言えるので throw
キーワードでスロー可能です。 MySubClass.php
ファイルの myMethod
メソッドを修正してみましょう。
<?php
require_once("MyClass.php");
require_once("MyException.php");
class MySubClass extends MyClass
{
public function myMethod($x)
{
if ($x == "") {
$e = new MyException();
throw $e;
}
echo "Override!" . PHP_EOL;
}
public function myMethod2()
{
echo "Hello World!" . PHP_EOL;
}
}
myMethod
メソッドにおいては引数 $x
が空文字だった場合に MyException
インスタンスをスローするように実装しています。
このようにスローした独自の例外クラス( Exception
クラスのサブクラス)も catch
ブロックに指定できます。my_class_runner.php
ファイルを修正してみましょう。
<?php
require_once("MySubClass.php");
try {
$myClass = new MySubClass("Hello");
$myClass->myMethod(""); #=> throw MyException
} catch (MyException $e) {
echo "Catch exception." . PHP_EOL;
}
プログラムを実行すると画面に Catch exception.
と表示されるでしょう。このように catch (MyException $e)
と実装することで MyException
インスタンスだけをキャッチするようになります。
以前のような
catch (Exception $e)
という実装はあまり好ましいものではありません。この場合Exception
クラスおよび、そのサブクラスのインスタンスもすべてキャッチしてしまうからです。開発の現場では独自の例外クラスを作成するなどして、キャッチ対象の例外クラスを具体的に指定することが一般的です。
PHPプログラムの開発(計算機例外クラス)
ここでは SimpleCalc
クラスの divide
メソッドにおいて、 0
による除算が発生した際に、独自の例外クラスである計算機例外( CalcException
)をスローするように変更します。
まずは計算機例外クラス( CalcException.php
)を作成します。
<?php
class CalcException extends Exception
{
const DIVIDE_BY_ZERO = "Divide by 0.";
}
CalcException
クラスでは extends
キーワードを指定してスーパークラスに Exception
クラスを指定しています。また class
定義時に const
キーワードによってクラス定数を定義できます。クラス定数は通常のプロパティのように値を変更することができません。変更のないデータを定義する際に利用します。またクラス定数はアクセス権が public
となります。
次に SimpleCalc
クラスの divide
メソッドを修正します。
<?php
require_once("CalcException.php");
class SimpleCalc
{
// ...省略
public function divide($x)
{
if ($x == 0) {
$e = new CalcException(CalcException::DIVIDE_BY_ZERO);
throw $e;
}
$this->number = $this->number / $x;
}
// ...省略
}
ここでは CalcException
クラスのコンストラクタ引数に CalcException::DIVIDE_BY_ZERO
を指定しています。このようにクラス定数にアクセスするには ::
スコープ定義演算子(ダブルコロン演算子)を指定します。
さいごに実行プログラム( calc_runner.php
)を修正します。
<?php
require_once("GreatCalc.php");
require_once("CalcException.php");
try {
$calc = new GreatCalc(10);
$calc->divide(0);
$calc->show();
} catch (CalcException $e) {
echo "CalcException: " . $e->getMessage() . PHP_EOL;
}
ここでは catch
ブロックでキャッチ対象の例外クラスに CalcException
を指定している点を確認しておきましょう。作成した例外クラスはこのように catch
ブロックに指定可能です。
それではコマンドラインからプログラムを実行してみましょう。
$ php calc_runner.php
CalcException: Divide by 0.
実行結果から divide
メソッドによってスローされた CalcException
を catch
ブロックで適切に処理できているのがわかります。
まとめ
- PHPの定義済みクラスを継承して新たなクラスを作成できる
- ユーザー例外
Exception
クラスを継承して独自の例外クラスを定義できる - 例外処理(
try - catch
文)のcatch
ブロックの引数に定義した例外クラスを指定できる