В настоящее время у меня есть набор классов Java та реализация a Processor
интерфейс, имея в виду у них всех есть a processRequest(String key)
метод. Идея состоит в том, что каждый класс имеет некоторых (скажите, <10), участник Strings
, и каждая из тех карт к методу в том классе через processRequest
метод, как так:
class FooProcessor implements Processor
{
String key1 = "abc";
String key2 = "def";
String key3 = "ghi";
// and so on...
String processRequest(String key)
{
String toReturn = null;
if (key1.equals(key)) toReturn = method1();
else if (key2.equals(key)) toReturn = method2();
else if (key3.equals(key)) toReturn = method3();
// and so on...
return toReturn;
}
String method1() { // do stuff }
String method2() { // do other stuff }
String method3() { // do other other stuff }
// and so on...
}
Вы получаете идею.
Это хорошо работало для меня, но теперь мне нужно доступное для времени выполнения отображение от ключа до функции; не каждая функция на самом деле возвращает Строку (некоторый возврат пусто), и я должен динамично получить доступ к типу возврата (использующий отражение) каждой функции в каждом классе, что существует ключ для. У меня уже есть менеджер, который знает обо всех ключах, но не отображении от ключа до функции.
Мой первый инстинкт должен был заменить это использование отображения if-else
операторы с a Map<String, Function>
, как я мог сделать в JavaScript. Но, Java не поддерживает первоклассные функции, таким образом, мне не повезло там. Я мог, вероятно, вскопать стороннюю библиотеку, которая позволяет мне работать с первоклассными функциями, но я еще не видел никого, и я сомневаюсь, что мне нужна вся новая библиотека.
Я также думал о помещении их String
ключи в массив и использование отражения для вызова методов по имени но я вижу две оборотных стороны к этому методу:
if-else
операторы я имею прямо сейчас. Эффективность является чем-то вроде беспокойства, потому что эти методы будут иметь тенденцию называться довольно часто, и я хочу минимизировать ненужные издержки.TL; DR: я ищу чистый, минимально-служебный путь к карте a String
к своего рода a Function
возразите, что я могу вызвать и звонить (что-то как) getReturnType()
на. Я особенно не возражаю пользоваться сторонней библиотекой, если она действительно соответствует моим потребностям. Я также не возражаю использовать отражение, хотя я сильно предпочел бы избегать использования отражения каждый раз, когда я делаю поиск метода - возможно, использующий некоторую кэширующуюся стратегию, которая объединяется Map
с отражением.
Мысли о хорошем способе получить то, что я хочу?Удачи!
А как насчет класса Method из API отражения? Вы можете найти методы класса по имени, параметрам или типу возвращаемого значения. Затем вы просто вызываете Method.invoke (this, parameters).
Это почти то же самое, что и карта из JavaScript, о которой вы говорите.
Этот example использует enum
именованных функций и абстрактный FunctionAdapter
для вызова функций с переменным числом однородных параметров без отражения. Функция lookup()
просто использует Enum.valueOf
, но Map
может стоить того для большого количества функций.
Как вы заметили, вы можете делать то, что хотите, используя Reflection API, но вы теряете некоторые преимущества компилятора Java, в дополнение к проблемам, которые вы уже придумали. Решит ли ваша проблема с переносом Strings в объект и использование шаблона Visitor? Каждый StringWrapper
принимает только Посетитель
, у которого есть правильный метод, или что-то в этом роде.
Используйте Map, где ключ - строка, а значение - объект, реализующий интерфейс, содержащий method(). Таким образом, вы можете получить из карты объект, содержащий нужный вам метод. Затем просто вызовите этот метод на объекте. Например:
class FooProcessor implements Processor{
Map<String, FooMethod> myMap;
String processRequest(String key){
FooMethod aMethod = myMap.getValue(key);
return aMethod.method();
}
}
Не существует первоклассных самостоятельных функций, но вы можете делать все, что хотите, с помощью интерфейса. Создайте интерфейс, который представляет вашу функцию. Например, у вас может быть следующее:
public interface ComputeString
{
public String invoke();
}
Затем вы можете создать объект Map
, как вы хотели в первую очередь. Использование карты будет намного быстрее, чем отражение, а также обеспечит большую безопасность типов, поэтому я бы посоветовал следующее.
Хотя вы не можете иметь функции первого класса, есть анонимные классы, которые могут быть основаны на интерфейсе:
interface ProcessingMethod {
String method();
}
Map<String, ProcessingMethod> methodMap = new HashMap<String, ProcessingMethod>();
methodMap.put("abc", new ProcessingMethod() {
String method() { return "xyz" }
});
methodMap.put("def", new ProcessingMethod() {
String method() { return "uvw" }
});
methodMap.get("abc").method();
Или вы можете использовать Scala :-)