Должны ли мы @Override реализации метода интерфейса?
Следует ли аннотировать метод, реализующий метод интерфейса @Override
?
Javadoc из Override
аннотация говорит:
Указывает, что объявление метода предназначено для переопределения объявления метода в суперклассе. Если метод аннотирован этим типом аннотации, но не переопределяет метод суперкласса, компиляторы обязаны генерировать сообщение об ошибке.
Я не думаю, что интерфейс технически суперкласс. Либо это?
16 ответов
Вы должны использовать @Override, когда это возможно. Это предотвращает совершение простых ошибок. Пример:
class C {
@Override
public boolean equals(SomeClass obj){
// code ...
}
}
Это не компилируется, потому что не корректно переопределяет public boolean equals(Object obj)
,
То же самое касается методов, которые реализуют интерфейс (только 1.6 и выше) или переопределяют метод класса Super.
Я считаю, что поведение javac изменилось - с 1.5 это запретило аннотацию, с 1.6 - нет. Аннотация предоставляет дополнительную проверку во время компиляции, поэтому, если вы используете 1.6, я бы пошел на это.
Вы должны всегда комментировать методы с @Override
если это доступно.
В JDK 5 это означает переопределение методов суперклассов, в JDK 6 и 7 это означает переопределение методов суперклассов и реализацию методов интерфейсов. Причина, как упоминалось ранее, заключается в том, что он позволяет компилятору перехватывать ошибки, когда вы думаете, что переопределяете (или реализуете) метод, но на самом деле определяете новый метод (другую сигнатуру).
equals(Object)
против equals(YourObject)
Пример является стандартным примером, но тот же аргумент может быть сделан для реализации интерфейса.
Я предполагаю, что причина, по которой нет необходимости аннотировать реализацию методов интерфейсов, состоит в том, что JDK 5 пометил это как ошибку компиляции. Если JDK 6 сделает эту аннотацию обязательной, это нарушит обратную совместимость.
Я не пользователь Eclipse, но в других средах разработки (IntelliJ) @Override
аннотация добавляется только при реализации методов интерфейса, если проект задан как проект JDK 6+. Я предположил бы, что Затмение похоже.
Тем не менее, я бы предпочел увидеть другую аннотацию для этого использования, может быть @Implements
аннотаций.
Я бы использовал это при каждой возможности. См. Когда вы используете аннотацию @Override в Java и почему?
JDK 5.0 не позволяет использовать @Override
аннотация, если вы реализуете метод, объявленный в интерфейсе (его ошибка компиляции), но JDK 6.0 позволяет это. Так что, может быть, вы можете настроить предпочтения вашего проекта в соответствии с вашими требованиями.
Читая javadoc в java8, вы можете найти следующее в объявлении переопределения интерфейса:
Если метод аннотирован этим аннотационным типом, компиляторы должны генерировать сообщение об ошибке, если не выполнено хотя бы одно из следующих условий:
- Метод переопределяет или реализует метод, объявленный в супертипе.
- Метод имеет сигнатуру, эквивалентную переопределению сигнатуры любого открытого метода, объявленного в {@linkplain Object}.
Поэтому, по крайней мере, в java8 вы должны использовать @Override для реализации метода интерфейса.
Если конкретный класс не переопределяет абстрактный метод, используя @Override
Поскольку реализация является открытым вопросом, так как компилятор неизменно предупредит вас о любых нереализованных методах. В этих случаях может быть выдвинут аргумент, что это ухудшает читабельность - в вашем коде читается больше вещей и, в меньшей степени, это называется @Override
и не @Implement
,
Если класс, который реализует interface
является abstract
учебный класс, @Override
полезно убедиться, что реализация предназначена для interface
Способ; без @Override
abstract
класс просто скомпилируется нормально, даже если сигнатура метода реализации не соответствует методу, объявленному в interface
; несоответствие interface
метод останется невыполненным. Документ Java, цитируемый @Zhao
Метод переопределяет или реализует метод, объявленный в супертипе.
явно относится к abstract
супер класс; interface
нельзя назвать супертипом. Так, @Override
является избыточным и не имеет смысла для interface
реализации методов в конкретных классах.
Переопределение ваших собственных методов, унаследованных от ваших собственных классов, обычно не нарушает рефакторинг с использованием ide. Но если вы переопределите метод, унаследованный от библиотеки, рекомендуется использовать его. Если вы этого не сделаете, вы часто получите не ошибку при более позднем изменении библиотеки, но хорошо скрытую ошибку.
Это не проблема с JDK. В Eclipse Helios он допускает аннотацию @Override для реализованных методов интерфейса, в зависимости от того, какой JDK 5 или 6. Как и в Eclipse Galileo, аннотация @Override не допускается, в зависимости от того, JDK 5 или 6.
Это может быть слишком поздний ответ. Но я надеюсь, что этот пример поможет кому-то понять, почему это так важно (для такого сценария)
public interface Restaurant(){
public boolean getBill();
public BigDecimal payAmount();
}
public interface Food() extends Restaurant{
public boolean haveSomeFood();
public boolean drinkWater();
}
public class Hungry() implements Food{
public boolean haveSomeFood(){}
public boolean drinkWater(){}
public boolean getBill(){}
public BigDecimal payAmount(){}
}
В приведенном выше примере, если я
Hungry
, я могу получить от
Restaurant
. Но если я взял реализацию ресторана, мне не нужно получать счет и не нужно платить сумму!!!!
Как?
- Интерфейс
Food
имеет ключевое словоextends Restaurant
- значит класс Hungry тоже реализован из интерфейса Restaurant. - Методы, фактически переопределяемые из интерфейса , не имеют ключевого слова
- Итак, если я удалю ключевое слово extends Restaurant (или, скажем, если я удалю интерфейс Restaurant, он не покажет никакой ошибки.
Если бы он был, всякий раз, когда я пытаюсь удалить интерфейс ресторана, он будет показывать ошибку компиляции.
Примечание . Когда вы реализуете интерфейс, вы можете не знать, расширяется ли этот интерфейс на другой интерфейс или может быть расширен, или наследование может быть удалено. Поэтому всегда лучше использовать
@override
ключевое слово
Проблема с включением @Override
является то, что это заставляет вас думать, что вы забыли позвонить super.theOverridenMethod()
метод, который очень сбивает с толку. Это должно быть кристально ясно. Возможно, Java должен предложить @Interface
для использования здесь. Ну да ладно, еще одна недоделанная особенность Java...
В Java 6 и более поздних версиях вы можете использовать @Override
для метода, реализующего интерфейс.
Но я не думаю, что это имеет смысл: переопределение означает, что у вас есть метод в суперклассе, и вы реализуете его в подклассе.
Если вы реализуете интерфейс, я думаю, что мы должны использовать @Implement
или что-то еще, но не @Override
,
Для меня часто это единственная причина, по которой некоторый код требует компиляции Java 6. Не уверен, стоит ли это того.
Затмение само добавит @Override
аннотация, когда вы говорите ему "генерировать нереализованные методы" во время создания класса, реализующего интерфейс.
Для интерфейса использование @Override вызвало ошибку компиляции. Итак, мне пришлось удалить его.
Сообщение об ошибке отправленоThe method getAllProducts() of type InMemoryProductRepository must override a superclass method
".
Это также читатьOne quick fix available: Remove @Override annotation.
"
Это было на Eclipse 4.6.3, JDK 1.8.0_144.