Различия между классом и закрытием уже были объяснены другими. Я просто хотел отметить, что во многих местах Java API, где язык, который их поддерживает, будет / может использовать замыкания, используется анонимная реализация интерфейса. Например, рассмотрите код ниже:
JButton btn = new JButton("Say Hello");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageBox("Hello");
}
});
В этом случае можно сказать, что анонимный ActionListener действует как замыкание, если Java допускает замыкания, код может выглядеть следующим образом: (с использованием синтаксиса c ++ 0x-esque)
JButton btn = new JButton("Say Hello");
btn.addActionListener([]=>(ActionEvent e){JOption.showMessageBox("Hello");});
В этом тривиальном случае основное различие между закрытием и анонимной реализацией интерфейса (AII) заключается в том, что:
- Метод AII имеет более строгую проверку типов, чем замыкание. (Системы замыкания могут быть сделаны для более строгой проверки типов, но в целом они не проверяются)
- Синтаксис закрытия требует меньше ввода. Похоже, это основной недостаток, который возникает после того, как вы изучаете Java, достаточно долго аргументы замыканий.
Мне еще предстоит столкнуться с ситуацией, когда AII не может делать то, что нужно делать. Да, есть еще типизация и другой интерфейс для определения, но система работает, и, IMHO, более мощная, так как вам не нужно использовать AII, а можно использовать полноценный класс со своими собственными методами, данными-членами и конструктором. , Пример - слушатель действия, который открывает контекстное меню. Если вы создаете класс, который реализует ActionListener и принимает JMenu в качестве аргумента, вы можете сделать:
btn.addActionListener( new ContextMenuActionListener(myMenu) );
Это выглядит чище (для меня), чем решение типа boost: bind type.
[]=>(ActionListener) myContextPopupClosure = []=>(ActionListener E){ ... };
...
btn.addActionListener( Closure.bind1(myContextPopupClosure,myMenu) );
или около того
EDIT:
Проработав вчера вечером много работы с дженериками, я понял одно преимущество замыканий над AII. В приведенных выше примерах я предполагал, что замыкание будет иметь тип [] => (ActionEvent), но в действительности оно может иметь тип [] => (? Super ActionEvent). Это значит:
[]=>(Object) c = []=>(Object o) { System.exit(0); }
btn.addActionClosure( c );
window.addMouseMovedClosure( c );
//Each method in MouseMotion listener would need it's own closure.
//So I 'invented' an API change.
Будет компилироваться. Это может оказаться полезным, когда вам нужно сделать одно и то же в ответ на несколько событий.
Другой пример. Это закрытие может быть добавлено в любое место, которое занимает закрытие. Если его добавить к чему-либо как ActionListener или MouseListener, он будет регистрировать вызовы.
[]=>(Object ... objs) log = []=>(Object ... obj) {for(Object o:obj){logObject(o);}}