Я смущен следующим кодом:
class MyException extends Exception {}
class AnotherException extends MyException {}
class Foo {
public function something() {
print "throwing AnotherException\n";
throw new AnotherException();
}
public function somethingElse() {
print "throwing MyException\n";
throw new MyException();
}
}
$a = new Foo();
try {
try {
$a->something();
} catch(AnotherException $e) {
print "caught AnotherException\n";
$a->somethingElse();
} catch(MyException $e) {
print "caught MyException\n";
}
} catch(Exception $e) {
print "caught Exception\n";
}
Я ожидал бы, что это произведет:
throwing AnotherException
caught AnotherException
throwing MyException
caught MyException
Но вместо этого это производит:
throwing AnotherException
caught AnotherException
throwing MyException
caught Exception
Кто-либо мог объяснить, почему это "перескакивает" через выгоду ($e MyException)?
Спасибо.
Обработчики исключений перехватывают исключение, вызванное кодом внутри области их блока try.
Вызов $ a-> somethingElse ()
НЕ происходит в блоке try, связанном с пропущенным обработчиком исключений. Это происходит в другом предложении catch.
Просто потому, что он физически появляется под линией, вызывающей исключение, недостаточно, чтобы заставить его покрыть этот код.
ИМХО, выбор стиля фигурных скобок делает это менее очевидным. Закрывающая фигурная скобка для предыдущего блока try появляется в той же строке, что и следующий захват, даже если они не связаны (ну, родственные) области.
Только потому, что для этого недостаточно места в комментарии. Думайте о try ... catch как о цикле if ... else. Вы не ожидаете, что следующее:
$a = 10;
if($a == 9)
print "\$a == 9";
elseif($a == 10) {
$a = 11;
echo "now \$a == 11";
} elseif($a == 11) {
echo "\$a == 11";
}
распечатает последнее условие ("\ $ a == 11"), потому что условие уже было выполнено первым elseif
. То же самое и с попыткой ... уловить. Если условие выполнено, поиск новых условий в той же области не продолжается.