Дизайн обработки исключений в двух наиболее популярных объектно-ориентированных средах (Java и .NET) основан на представлении о том, что вопрос о том, обрабатывать ли конкретное исключение, должен зависеть в первую очередь от его типа, и что типы исключения, которые вы захотите отловить, будут иметь иерархические классовые отношения. Я думаю, что Java и .NET делают это таким образом, потому что C ++ делал это именно так, а C ++ делал это таким образом из-за желания избежать жесткой привязки любых не примитивных типов, жестко запрограммированных в языке. В отсутствие жестко закодированного типа, к которому можно привести все исключения, оператор catch
не может знать что-либо о любом типе исключения, для которого он явно не подготовлен. Если имеет смысл только перехватывать исключения, которые можно декодировать, оператор catch
сможет разумно воздействовать на эти типы и только на те типы, которые являются производными от того, который содержится в операторе.
В ретроспективе, вероятно, было бы лучше, чтобы решения о том, над какими исключениями следует действовать и / или разрешать с помощью конкретных операторов catch
, определялись другими способами, помимо иерархии классов. Среди прочего, одна попытка вызвать метод может потерпеть неудачу из-за множества проблем; если это произойдет, каждый catch
, связанный с любым из этих проблем, должен сработать, но только когда все проблем были решены, должно возобновиться нормальное выполнение. К сожалению, ни в Java, ни в .NET нет механизма для достижения такого поведения.
Что касается макета верхнего уровня иерархии, я думаю, что было предположение, что любой тип исключения, который может быть вызван методом, всегда будет ожидаться кодом непосредственного вызова или никогда не ожидаться никаким кодом вызова. , Исключения последнего типа были классифицированы как Error
или RuntimeException
, тогда как исключения первого типа были размещены в другом месте. На практике вопрос о том, ожидается ли исключение вызывающей стороной метода, не должен зависеть от его места в иерархии или даже от типа исключения . Тот факт, что метод объявлен как throws FooException
, не означает, что вызывающий код всегда будет ожидать, что может произойти исключение. В коде очень часто вызывается метод, который объявлен как выбрасывающий исключение, но полагаю, что обстоятельства, связанные с вызовом, таковы, что на практике конкретный вызов никогда не сгенерируется. Если исключение действительно происходит, оно должно вести себя как неожиданное исключение, , даже если внешний контекст выполнения ожидает перехват исключения этого типа . К сожалению, механизмы обработки исключений - это то, чем они являются, и я не ожидаю какого-либо серьезного пересмотра.