Использование произвольно определенного метода анонимного интерфейса
Рассмотрим следующий код:
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
, а не как экземпляр нашего нового, анонимного дочернего класса.
Итак, мой вопрос: есть ли "хороший" способ достичь такого поведения? Помимо очевидного (просто для того, чтобы правильно объявить класс).
Ответы
Ответ 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();
}