@MustOverride аннотация? - PullRequest
       17

@MustOverride аннотация?

13 голосов
/ 30 апреля 2010

В .NET можно указать атрибут «mustoverride» для метода в конкретном суперклассе, чтобы подклассы переопределяли этот конкретный метод. Мне было интересно, есть ли у кого-нибудь пользовательская Java-аннотация, которая могла бы достичь того же эффекта. По сути, я хочу подтолкнуть подклассы переопределить метод в суперклассе, который сам по себе имеет некоторую логику, которую необходимо выполнить. Я не хочу использовать абстрактные методы или интерфейсы, потому что я хочу, чтобы некоторые суперфункции запускались в супер-методе, но более или менее выдают предупреждение / ошибку компилятора, указывающее, что производные классы должны переопределить данный способ.

Ответы [ 7 ]

19 голосов
/ 11 января 2011

Я не совсем понимаю, почему вы не захотите использовать абстрактный модификатор - он предназначен для принудительной реализации подклассом и должен использоваться только для некоторых методов, а не для всех. Или, может быть, вы думаете о «чистых абстрактных» классах в стиле C ++?

Но еще одна вещь, о которой многие Java-разработчики не знают, это то, что можно также переопределить неабстрактные методы и объявить их абстрактными; как:

public abstract String toString(); // force re-definition

так что, хотя java.lang.Object уже определяет реализацию, вы можете заставить подклассы определять ее снова.

12 голосов
/ 30 апреля 2010

Игнорирование абстрактных методов, в Java такого средства не существует. Возможно, возможно создать аннотацию во время компиляции, чтобы вызвать такое поведение (и я не уверен, что это так), но это все.

Настоящий кикер - это «переопределить метод в суперклассе, который сам по себе имеет некоторую логику, которую необходимо выполнить». Если вы переопределите метод, метод суперкласса не будет вызван, если вы не вызовете его явно.

В подобных ситуациях я обычно делал что-то вроде:

abstract public class Worker implements Runnable {
  @Override
  public final void run() {
    beforeWork();
    doWork();
    afterWork();
  }

  protected void beforeWork() { }
  protected void afterWork() { }
  abstract protected void doWork();
}

для навязывания определенной логической структуры по методу интерфейса. Вы можете использовать это, например, для подсчета вызовов, не беспокоясь о том, вызывает ли пользователь super.run() и т. Д.

5 голосов
/ 30 апреля 2010

... и если объявление базового класса abstract не является опцией, вы всегда можете выбросить исключение UnsupportedOperationException

class BaseClass {
    void mustOverride() {
        throw new UnsupportedOperationException("Must implement");
    }
}

Но это, конечно, не проверка во время компиляции ...

4 голосов
/ 30 апреля 2010

Я не уверен, о каком атрибуте вы думаете в .NET.

В VB вы можете применить модификатор MustOverride к методу, но это эквивалентно тому, чтобы сделать метод абстрактным в Java. Вам не нужен атрибут / аннотация, так как концепция встроена в языки. Это больше, чем просто применение метаданных - есть также принципиальное отличие в том, что абстрактный метод не включает в себя саму реализацию.

Если вы действительно думаете, что есть такой атрибут, пожалуйста, не могли бы вы сказать, какой из них вы имеете в виду?

2 голосов
/ 16 июня 2015

В Android появилась новая аннотация, анонсированная в Google I / O 2015: @ CallSuper

Подробнее здесь: http://tools.android.com/tech-docs/support-annotations

1 голос
/ 30 июля 2011

Если вам нужно какое-то поведение по умолчанию, но по какой-то причине оно не должно использоваться специализациями, как, например, реализация логики в неабстрактном классе Adapter просто для простоты создания прототипов, но которую не следует использовать, например, в производстве, Вы можете инкапсулировать эту логику и записать предупреждение о том, что она используется, без необходимости ее запуска.

Конструктор базового класса может проверить, указывает ли переменная, содержащая логику, значение по умолчанию. (писать в очень абстрактных терминах, так как я думаю, что это должно работать на любом языке)

Это будет что-то вроде этого (не скомпилированный, непроверенный и неполный) пример Java (до 7):

public interface SomeLogic {
 void execute();
}

public class BaseClass {

  //...private stuff and the logging framework of your preference...

  private static final SomeLogic MUST_OVERRIDE = new SomeLogic() {
    public void execute() {
      //do some default naive stuff
    }
  };

  protected SomeLogic getLogic() { return MUST_OVERRIDE; }

  //the method that probably would be marked as MustOverride if the option existed in the language, maybe with another name as this exists in VB but with the same objective as the abstract keyword in Java
  public void executeLogic() {
    getLogic().execute();
  }

  public BaseClass() {
    if (getLogic() == MUST_OVERRIDE) {
      log.warn("Using default logic for the important SomeLogic.execute method, but it is not intended for production. Please override the getLogic to return a proper implementation ASAP");
    }
  }

}

public GoodSpecialization extends BaseClass {

  public SomeLogic getLogic() {
    //returns a proper implementation to do whatever was specified for the execute method
  }

  //do some other specialized stuff...
}

public BadSpecialization extends BaseClass {

  //do lots of specialized stuff but doesn't override getLogic...
}

Некоторые вещи могут отличаться в зависимости от требований и явно проще, особенно для языков с лямбда-выражениями, но основная идея будет такой же.

Без встроенной вещи всегда есть какой-то способ ее эмулировать, в этом примере вы получите предупреждение во время выполнения в файле журнала с домашним шаблоном, похожим на решение, что только ваши потребности должны указывать, если этого достаточно или более жесткие манипуляции с байт-кодом, разработка идеальных плагинов или все, что нужно от волшебства.

0 голосов
/ 12 ноября 2015

Я думал об этом.

Хотя я не знаю ни одного способа требовать его с ошибкой компиляции, вы можете попробовать написать собственное правило PMD, чтобы поднять красный флаг, если вы забыли переопределить.

Уже есть множество правил PMD, которые напоминают вам о реализации HhashCode, если вы решили переопределить equals. Возможно, что-то можно сделать так.

Я никогда не делал этого раньше, так что я не тот, кто пишет учебник, но хорошее место для начала - эта ссылка http://techtraits.com/programming/2011/11/05/custom-pmd-rules-using-xpath/ В этом примере он в основном создает небольшое предупреждение, если вы решили использовать подстановочный знак в пакете импорта. Используйте его в качестве отправной точки для изучения того, как PMD может анализировать ваш исходный код, посещать каждого члена иерархии и определять, где вы забыли реализовать конкретный метод.

Аннотации также возможны, но вам нужно найти свой собственный способ реализации навигации по пути классов. Я считаю, что PMD уже справляется с этим. Кроме того, PMD имеет действительно хорошую интеграцию с IDE. https://pmd.github.io/

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