0

Рассмотрим следующий пример:аннотаций для поддержки рефакторинга функционального интерфейса

public interface Greeter { 
    String greet(); 
} 

public class ExplicitGreeterImpl implements Greeter { 
    @Override 
    public String greet() { 
     return "Hello World!"; 
    } 
} 

public class ImplicitGreeterImpl { 
    public String doTheGreeting() { 
     return "Hello World!"; 
    } 
} 

private void run() { 
    System.out.println(new ExplicitGreeterImpl().greet()); 

    Greeter foo = new ImplicitGreeterImpl()::doTheGreeting; 
    System.out.println(foo.greet()); 
} 

Функциональный интерфейс Greeter имеет две реализации. ExplicitGreeterImpl применяет Greeter, используя пункт implements, а ImplicitGreeterImpl::doTheGreeting осуществляет Greeter без него. Тем не менее, ImplicitGreeterImpl::doTheGreeting предназначен для реализации Greeter, как и ExplicitGreeterImpl.

Теперь я хочу, чтобы реорганизовать интерфейс Greeter, так что я могу передать имя ему:

public interface Greeter { 
    String greet(String name); 
} 

я могу сделать это с Signature рефакторинга Изменить метод, предоставляемого Затмение (я уверен, что другого IDE имеют аналогичный рефакторинг). Это автоматически обновляет все реализации и способы использования интерфейса Greeter. Реализации получают новый параметр, в то время как обычаи передают настраиваемое значение по умолчанию. Это отлично подходит для ExplicitGreeterImpl, однако рефакторинг не касается метода ImplicitGreeterImpl::doTheGreeting. Таким образом, назначение

Greeter foo = new ImplicitGreeterImpl()::doTheGreeting; 

будет ошибкой времени компиляции. Чтобы исправить это, мне нужно вручную настроить подпись метода ImplicitGreeterImpl::doTheGreeting.

Теперь я понимаю, что во многих случаях нежелательно автоматически настраивать подпись ImplicitGreeterImpl::doTheGreeting. Тем не менее, я чувствую, что текущий рабочий процесс может быть улучшен:

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

Например, ImplicitGreeterImpl может выглядеть следующим образом:

public class ImplicitGreeterImpl { 
    @Implements(Greeter.class) 
    public String doTheGreeting() { 
     return "Hello World!"; 
    } 
} 

Теперь инструменты рефакторинга может быть уверен, что ImplicitGreeterImpl::doTheGreeting предполагается реализовать Greeter и, таким образом, они могут автоматически изменить свою подпись.

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

ответ

0

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

public interface Greeter { 
    String greet(); 
} 

public enum EnumGreeterImpl implements Greeter { 
    GREETER1 { 
     @Override 
     public String greet() { 
      return "Hello World!"; 
     } 
    }, 
    GREETER2 { 
     @Override 
     public String greet() { 
      return "Foo bar"; 
     } 
    }, 
} 

private void run() { 
    Greeter foo = EnumGreeterImpl.GREETER1; 
    System.out.println(foo.greet()); 
} 

Смотрите также:

0

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

+0

Там действительно хороший причина не реализовывать интерфейс напрямую, а использовать ссылку на метод. Рассмотрим шаблон команды. В этом случае: (1) Интерфейс Command, вероятно, является функциональным интерфейсом, (2) существует множество реализаций интерфейса Command и (3) каждая из этих реализаций очень проста. Добавление дополнительного класса для каждой из этих реализаций добавляет много шума в код. Однако, если каждая реализация Command является всего лишь методом, код становится намного чище. –