2016-08-27 3 views
0

Я чувствую, что мне что-то не хватает, когда речь заходит о статически типизированных языках. Когда я в значительной степени использовал perl путь назад, было много способов, которыми я мог бы сказать объект, который вызывается.Передача метода-ссылки на конструктор объектов

Теперь, когда я нахожусь в Java, я не понимаю, как я могу сделать что-то подобное в легком фьюжне

У меня есть общий Button класса. Это подклассифицировано всеми фактическими кнопками, которые будут использоваться: каждый с другим методом для вызова при нажатии.

Не существует способа передать ссылку на метод вызова при нажатии, чтобы я мог использовать один класс для всех кнопок?

В настоящее время я создаю кнопки, как это:

// Specifically using the subclass that sets "firemode" to "close" 
FiremodeClose fc = new FiremodeClose(Settings.ui_panel_start, Settings.ui_panel_row_firemode, game); 
painter.addSelectionButton(fc); 
clickTracker.addSelectionButton(fc); 

Это конечно couses множество подклассов, каждый из которых отличаясь только размещения, этикетки/графики и вызова метода. Это имеет смысл делать что-то похожее на это:

// Generic button, the method that sets "firemode" is somehow passed as arguement to the contsructor. 
Button fc = new Button(&referenceToFunctionToCallWhenClicked, otherArguementsEtc); 
painter.addSelectionButton(fc); 
clickTracker.addSelectionButton(fc); 

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

+2

Для этого нужен интерфейс. Java 8 и Groovy создают встроенные интерфейсные реализации для таких случаев, как это просто. – chrylis

+0

^^^ Это и посмотреть также анонимные классы. –

+0

@chrylis Если это то, для чего нужны интерфейсы, тогда я, должно быть, использовал их для чего-то другого, кроме их намеченной цели. Мне бы хотелось увидеть ответ, содержащий некоторые примеры кода для этого. – Jarmund

ответ

1

Если это то, для чего нужны интерфейсы, я должен использовать их для чего-то другого, кроме их намеченной цели. Мне бы хотелось увидеть ответ, содержащий некоторые примеры кода для этого.

иметь свой Buttons реализовать observer pattern, так же, как Swing does. Тогда вы можете просто использовать интерфейс Swing ActionListener, или даже Runnable не является плохим выбором, или, например, рулонные:

// Your interface. 
public interface MyButtonListener { 
    public void buttonClicked(); 
} 

// Somewhere else: 
Button fc = ...; 
fc.addButtonListener(new MyButtonListener() { 
    @Override public void buttonClicked() { 
     // do stuff here 
    } 
}); 

// And in your Button have it simply iterate through all of its registered 
// MyButtonListeners and call their buttonClicked() methods. 

Есть множество способов реализации этого.Например, вы могли бы даже сделать что-то вроде:

public interface ThingThatCaresAboutButtons { 
    public void buttonClicked (Button button); 
} 

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

public class MyUI implements ThingThatCaresAboutButtons { 
    @Override public void buttonClicked (Button button) { 
     if (button == theOneButton) { 
      // do whatever 
     } else if (button == theOtherButton) { 
      // do whatever 
     } 
    } 
} 

И при создании кнопки:

theOneButton = new Button(theUI, ...); 
theOtherButton = new Button(theUI, ...); 

Или есть их сохраняйте список вместо одного объекта, переданного в конструкторе. Или что угодно.

Бесконечные способы кожи этой кошки, но, надеюсь, вы получаете вдохновение здесь. Посмотрите, как работает Swing.

1

Вы можете, например, использовать Runnable:

class MyButton { 
    private final Runnable action; 

    public MyButton(Runnable action) { 
     this.action = action; 
    } 
    ... 
} 

И затем вызвать action.run() при нажатии на кнопку.

Тогда при создании кнопки вы можете передать reference to a method, если у него есть возвращаемый тип void и не принимает никаких аргументов.

Button fc = new Button(EnclosingClass::methodToCall, otherArguementsEtc); 

Другие интерфейсы могут использоваться для различных сигнатур методов.

1

В Java 8 вы можете использовать обе ссылки и лямбды метод:

class Button { 
    Button(Runnable function) { 
    } 
} 
Button b1 = new Button(() -> System.out.println("works!")); 
Button b2 = new Button(System::gc); 

Вы можете сделать то же самое в Java < 8, но это более многословным анонимных классов:

Button b3 = new Button(new Runnable() { 
    @Override 
    public void run() { 
     System.out.println("works!"); 
    } 
});