Exception類的子類
有兩個理由讓我們想要從Exception類中派生中子類:
1. 讓子類提供自定義的功能;
2. 區分不同類型的異常;
看第二個例子。使用CommandManager類時我們可能會產生兩個錯誤:一個是一般性的錯誤如找不到目錄,另一個是找不到或無法生成Command對象。這樣我們需要針對這兩個錯誤來定義兩種異常子類型。
index_php5_4.php
// PHP 5
require_once('cmd_php5/Command.php');
class CommandManagerException extends Exception{}
class IllegalCommandException extends Exception{}
class CommandManager {
private $cmdDir = "cmd_php5";
function __construct() {
if (!is_dir($this->cmdDir)) {
throw new CommandManagerException("directory error: $this->cmdDir");
}
}
function getCommandObject($cmd) {
$path = "{$this->cmdDir}/{$cmd}.php";
if (!file_exists($path)) {
throw new IllegalCommandException("Cannot find $path");
}
require_once $path;
if (!class_exists($cmd)) {
throw new IllegalCommandException("class $cmd does not exist");
}
$class = new ReflectionClass($cmd);
if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
throw new IllegalCommandException("$cmd is not a Command");
}
return $class->newInstance();
}
}
?>
當我們的類不能找到正確的command目錄時,將拋出一個CommandManagerException異常;當在生成Command對象時產生錯誤,則getCommandObject()方法將拋出一個IllegalCommandException異常。注意存在多個可能導致拋出IllegalCommandException異常的原因(如未找到文件,或在文件中未找到正確的類)。我們將前兩個例子結合起來并為IllegalCommandException提供整型的錯誤標識常量來代表不同類型的出錯原因。
現在CommandManager類已經具備了處理這多種出錯情況的能力,我們可以增加新的catch語句來匹配不同的錯誤類型。
index_php5_4.php 后半段
// PHP 5
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
} catch (CommandManagerException $e) {
die($e->getMessage());
} catch (IllegalCommandException $e) {
error_log($e->getMessage());
print "attempting recovery/n";
// perhaps attempt to invoke a default command?
} catch (Exception $e) {
print "Unexpected exception/n";
die($e->getMessage());
}
?>
如果CommandManager 對象拋出一個CommandManagerException異常,則相對應的catch語句將會執行。每個catch語句的參數就像是一個匹配測試一樣,第一個發生匹配的catch語句將會執行,而不執行其它的catch語句。所以,你應當將針對特定異常的catch語句寫在前面,而將針對一般性的異常的catch語句寫在后面。
如果你將catch語句這樣寫:
// PHP 5
try {
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
} catch (Exception $e) {
print "Unexpected exception/n";
die($e->getMessage());
} catch (CommandManagerException $e) {
die($e->getMessage());
} catch (IllegalCommandException $e) {
error_log($e->getMessage());
print "attempting recovery/n";
// perhaps attempt to invoke a default command?
}
?>
那么當異常拋出時,不管是什么異常第一個catch語句catch (Exception $e){}將總是被執行。這是由于任何異常都從屬于Exception類型,所以總是匹配。這就達不到我們所要的針對特定異常進行不同處理的目的。
如果你在捕捉特定類型的異常,那么在最后一個catch語句中捕捉Exception類型的異常是一個好主意。最后一個catch語句表示catch-all,捕捉所有異常。當然,你可能不想馬上處理異常,而是想要將它傳遞,然后在適當的時候處理。這是PHP的異常機制中另一個需要討論的地方。
原文轉自:http://www.anti-gravitydesign.com