Полиморфизм и проверка на исключение в абстрактных методах - PullRequest
0 голосов
/ 20 июня 2019

Предположим, у нас есть класс Foo с одним методом, который может выдать IOException.

public abstract class Foo {
    public abstract void foo() throws IOException;
}

Однако, когда я расширяю этот класс как FooImpl, вот так:

public class FooImpl extends Foo {
    public void foo() throws Exception {
        throw new Exception("This cannot throw!");
    }
}

Это приводит к ошибке времени компиляции: «Перезаписанный метод не генерирует исключение java.lang.Exception»

Я понимаю, что это потому, что переопределяющий метод "может выбрасывать только проверенные исключения своего родительского метода и любые непроверенные исключения"

Почему это так? Почему мы должны запрещать себе создавать более широкое исключение?

(я тоже ищу обходной путь)

Спасибо!

Ответы [ 2 ]

4 голосов
/ 20 июня 2019

Вы всегда должны иметь возможность использовать подкласс везде, где используется его суперкласс.Это в значительной степени буквально определение подкласса, и в более общем смысле его называют принцип подстановки Лискова .

Так что следующее должно работать, учитывая это определение Foo:

Foo foo = getFooFromSomewhere();
try {
  foo.foo();
} catch (IOException e) {
  // handle e
}

... поскольку это соответствует определению Foo.

Для этого определения FooImpl это будет работать , а не , потому что Exception, которые не IOException, не обрабатываются, и как проверенные исключения они должны быть перехвачены или иным образом.обрабатываются.

0 голосов
/ 20 июня 2019

Это из-за контракта, установленного суперклассом.Другими словами, когда компилятор «проверяет» переопределенный метод, он гарантирует, что программирование с использованием API супертипа будет возможно с использованием экземпляра подкласса.

Практически, если у вас было

Foo foo = some foo implementation;
try {
    foo.foo();
} catch(IOException ioe) {
    //handle IOException
}

Этот блок catch должен быть достаточным для обработки проверенного исключения API Foo.Но если компилятор разрешил подклассам вызывать проверенные исключения, отличные от объявленных суперклассом, например Exception, то программирования против Foo и обработки всех объявленных проверенных исключений будет недостаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...