РНР 5 в подлиннике

Страница 342 из 554


Гпава 34, Обработка ошибок и исключения

691

echo "Конец программы.<Ьг>"; // Функция-обработчик, function handler($num, $str) {

// Код обработчика.

echo "Ошибка: $str<br>"; // exit(); }

?>

Первое, что бросается в глаза, — это излишняя многословность кода. Но давайте пойдем дальше и посмотрим, какой результат выдает данная программа:

Начало программы.

Все, что имеет начало...

Ошибка: Hello!

За счет использования exit О в функции handler)) наша новая программа не только подвергает сомнению известный тезис (см. операторы echo), но также и утверждает, что любая, даже малейшая, ошибка является фатальной!

Что ж, раз проблема в команде exit о, попробуем ее убрать из скрипта. Мы увидим следующий результат:

Начало программы.

Все, что имеет начало...

Ошибка: Hello!

...имеет и конец.

Конец программы.

И снова мы получили не то, что нужно: ошибка теперь уже не является "чересчур фатальной", как раньше, у нее противоположная проблема: она, наоборот, недостаточно фатальна.

Мы-то хотели разрушать идиому о конечности всего, что имеет начало, а получили — просто робкое замечание, произнесенное шепотом из-за кулис.

Обычно все серьезные ошибки в программе (и внутренние, и пользовательские) поддаются некоторой классификации. Механизм обработки исключений, помимо основного своего достоинства — возможности отделения кода обработки ошибки от кода ее генерации — имеет и еще один плюс. Он заключается в возможности перехвата исключений по их видовой принадлежности на основе иерархии классов. При этом каждое исключение может принадлежать одновременно нескольким видам, и перехватываться с учетом совпадения своего (или родительского) вида.

Листинг 34.6 иллюстрирует тот факт, что при перехвате исключений используется информация о наследовании классов-исключений.

Классификация и наследование

692

Часть V. Объектно-ориентированное программирование на РНР

| Листинг 34.6. Файл inherit.php

<?php ## Наследование исключений. // Исключение — ошибка файловых операций. class FilesystemException extends Exception { private $name;

public function _construct($name) {

parent::_construct($name);

$this->name = $name;

public function getNamef) { return $this->name; }

}

// Исключение — файл не найден.

class FileNotFoundException extends FilesystemException {} // Исключение — Ошибка записи в файл.

class FileWriteException extends FilesystemException {} try {

// Генерируем исключение типа FileNotFoundException. if (!file_exists("spoon"))

throw new FileNotFoundException("spoon") ; } catch (FilesystemException $e) { // Ловим ЛЮБОЕ файловое исключение!

echo "Ошибка при работе с файлом '{$e->getName()}'.<br>"; } catch (Exception $e) (

// Ловим все остальные исключения, которые еще не поймали, echo "Другое исключение: ($e->getDirName()}.<br>";

В программе мы генерируем ошибку типа FileNotFoundException, однако, ниже перехватываем исключение не прямо ЭТОГО класса, а его "родителя" — FilesystemException.

Так как любой объект типа FileNotFoundException является также и объектом класса FilesystemException, блок catch "срабатывает" для него. Кроме того, на всякий случай мы используем блок "поимки" объектов класса Exception — "родоначальника" всех исключений. Если вдруг в программе произойдет исключение другого типа (обязательно производного от Exception), оно также будет обработано.

К сожалению, в современной версии РНР реализация исключениями интерфейсов (а следовательно, и множественная классификация) не поддерживается. Точнее, вы можете создать класс-исключение, наследующий некоторый интерфейс, но попытка перехватить сгенерированное исключение по имени его интерфейса (а не по имени класса) не даст результата. Есть основания надеяться, что в будущих версиях РНР данное неудобство будет устранено.

Базовый класс Exception

РНР последних версий не допускает использования объектов произвольного типа в качестве исключений. Если вы создаете свой собственный класс-исключение, то должны унаследовать его от встроенного типа Exception.

?>




  Hostland.Ru

 «Бесплатный хостинг Hostland.Su» © 2006