Подтвердить что ты не робот

Использование произвольно определенного метода анонимного интерфейса

Рассмотрим следующий код:

public static void main(String[] args) {
    File file = new File("C:\\someFile.txt") {
        public void doStuff() {
            // Do some stuff
        }   
    };

    file.doStuff(); // "Cannot resolve method"
}

Когда мы пытаемся назвать наш новый метод doStuff(), это невозможно. Причиной этого является то, что file объявляется как объект типа file, а не как экземпляр нашего нового, анонимного дочернего класса.

Итак, мой вопрос: есть ли "хороший" способ достичь такого поведения? Помимо очевидного (просто для того, чтобы правильно объявить класс).

4b9b3361

Ответ 1

Это невозможно, потому что вы пытаетесь вызвать подкласс метода на ссылку суперкласса. И этот метод не определен в самом суперклассе. Анонимный класс - это просто подкласс File.

Однако обходным путем является переход через отражение:

file.getClass().getMethod("doStuff").invoke(file);

Метод getClass() вернет тип выполнения File, а затем вы можете получить метод для этого класса, используя Class#getMethod().

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

Ответ 2

Хороший способ - не использовать анонимный внутренний класс в вашем случае, а определить свой собственный класс, который расширяет File и добавлять любые методы, которые вам там нужны.

class StuffedFile extends File {
    // implement all needed constructors
    public void doStuff() { /*.....*/}
}

Теперь вы можете использовать его как:

MyFile f = new MyFile("...");
f.doStuff();

Однако вся эта попытка расширения File не кажется хорошим дизайном. Создайте другой класс, который может принимать файл и делать на нем все. Вы достигнете лучшей инкапсуляции и повторного использования кода.

ИЗМЕНИТЬ Очевидно, вы можете использовать отражение для вызова любого метода, который вы хотите, но я не могу назвать это "приятное решение". Я могу назвать это "возможным обходным путем".

Ответ 3

Ближайший я смог дойти до вашего уровня лаконичности:

public static void main(String[] args) {
  abstract class FileThatDoesStuff extends File {
    // Need a constructor that takes a String because File has one.
    public FileThatDoesStuff(String filePath) {
      super(filePath);
    }
    // It also does stuff.
    public abstract void doStuff();
  }
  FileThatDoesStuff file = new FileThatDoesStuff("C:\\someFile.txt") {
    @Override
    public void doStuff() {
      // Do some stuff
    }

  };
  file.doStuff(); // "Can resolve method"
}

Я должен признать, что я мог бы сделать:

abstract class DoesStuff<T> extends T {
  public abstract void doStuff();
}

Ответ 4

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

public static void main(String[] args) {
   new File("C:\\someFile.txt") {
      public void doStuff() {
          // Do some stuff
      }   
   }.doStuff();
}