2010-09-13 2 views
0

В Java можно ли связать некоторый объект (т. Е. String) с вызываемой функцией?Определение функции обратного вызова для заданного значения

У меня есть два одинаковых меню и оба имеют onClickListener с некоторым кодом, как это:

if (item.id==0) { 
doSomeFunction(argument); 
} 
else if (item.id==1) { 
doSomeOtherFunction(); 
} 
else if (item.id==2) { 
doStuff(arg2); 
} 
else { 

} 

Я хотел бы иметь объект (т.е. Hashtable), который позволил бы мне определить ассоциации между «пунктом. id "->" код для выполнения ".

Пример:

0 -> doSomeFunction(argument); 
1 -> doSomeOtherFunction(); 
2 -> doStuff(arg2); 

В результате я мог пропустить эти условные и просто выполнить вызов функции функции, сохраненной для данного item.id.

Например, с помощью Lisp я мог бы связать item.id с функцией, а затем использовать «funcall» Lisp для вызова этой функции.

Есть ли стандартный способ сделать что-то подобное на Java?

Существуют ли альтернативные решения для пропуска условных обозначений?

Обратите внимание, что вызываемым функциям может потребоваться получение параметров.

Спасибо.

ответ

3

Поскольку вам не нужно возвращать какие-либо значения, вам не нужно возвращать какие-либо значения, вы можете связать каждый ID-ключ с объектом Runnable, который вызывает метод, который вы хотите. Например:

Map<Integer, Runnable> map = ...; 
map.put(0, new Runnable() { 
    public void run() { 
    doSomeFunction(); 
    } 
}); 

map.get(0).run(); 

Если вам нужны методы, чтобы иметь возможность возвращать значение, вы можете использовать Callable вместо Runnable. Вы также можете создать свой собственный аналогичный интерфейс и использовать его, если необходимо.

В настоящее время в Java этот вид вещей должен выполняться с экземпляром класса с одним абстрактным методом, таким как Runnable. Java 7 или 8 (в зависимости от того, как они решат продолжить) добавят лямбда-выражения и ссылки на методы, которые, я думаю, являются тем, что вы действительно хотите. Ссылки на методы позволят вам сделать что-то подобное (используя Map<Integer, Runnable>, как указано выше).

map.put(0, Foo#doSomeFunction()); 

Edit:

Ваше обновление показывает, что некоторые из этих методов должны были бы иметь аргументы, переданные им. Однако вы, кажется, просите о двух разных вещах. В вашем примере объявляя отображения указаны

0 -> doSomeFunction(argument); 
1 -> doSomeOtherFunction(); 
2 -> doStuff(arg2); 

аргументов, указав, что они являются либо значениями, которые доступны в то время, вы объявляете отображение или они поле в классе или некоторых таких. В любом случае, вы были бы в состоянии объявить их при создании Runnable:

new Runnable() { 
    public void run() { 
    doSomeFunction(argument); 
    } 
} 

Здесь argument должен либо быть поле или быть объявлены final.

Если, с другой стороны, у вас нет ссылок на аргументы во время создания сопоставления, вам нужно создать некоторый согласованный интерфейс, который могли бы использовать все вызовы методов. Например, наименьший общий интерфейс, который может работать для вашего образца будет один, который объявил два параметра и void возврата:

public interface CustomRunnable<T,G> { 
    public void run(T arg1, G arg2); 
} 

Тогда вы могли бы:

map.put(0, new CustomRunnable<Foo,Bar>() { 
    public void run(Foo arg1, Bar arg2) { 
    doSomeFunction(arg1); 
    } 
}); 
map.put(1, new CustomRunnable<Foo,Bar>() { 
    public void run(Foo arg1, Bar arg2) { 
    doSomeOtherFunction(); 
    } 
}); 
map.put(2, new CustomRunnable<Foo,Bar>() { 
    public void run(Foo arg1, Bar arg2) { 
    doStuff(arg2); 
    } 
}); 

Каждый CustomRunnable использует только аргументы что ему нужно, если таковые имеются. Тогда вы могли бы сделать вызов, как это:

map.get(item.id).run(argument, arg2); 

Очевидно, что это становится довольно некрасиво, но это в значительной степени то, что вы должны сделать в этом случае.

+0

+1 для интересных примеров и для обозначения возможных Lambdas в Java 7/8. – MyNameIsZero

1

Да, есть несколько способов сделать это. Одним из примеров является реализация интерфейса анонимно и хранить его в HashMap, что-то вроде этого:

public class MyListeningClass 
{ 
    ... 

    public interface MyEventHandler 
    { 
     public void handle(String myParam); 
    } 

    private HashMap<ItemType, MyEventHandler> eventHandlers= new HashMap<ItemType, MyEventHandler>(); 

    initItems() 
    { 
     //do for each item 
     eventHandlers.put(item1, new MyEventHandler(){public void handle(String myParam){ 
        //do whatever I want to 
       }}); 
    } 

    myListeningMethod(ItemType item) 
    { 
     eventHandlers.get(item).handle("a parameter"); 
    } 
} 
0

Java Swing, способ ответа на это класс действий. в основном это соответствует шаблону команды ...

1

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

Вы не говорите, какую библиотеку вы используете. onClickListener не качели, но если вы использовали Swing, вы бы хотели JMenuItem.addActionListener.

+0

Библиотека, которую я использую, относится к «Android» (мобильная ОС). Благодарю. – MyNameIsZero

Смежные вопросы