2009-12-12 1 views
5

Мне интересно о стандартной практике с внутренними классами (на Java, но я полагаю, что это относится ко всем языкам OO). Итак, у меня есть подкласс JFrame ControllerWindow, который содержит подкласс JPanel MapPanel, на который я рисую (так что ему нужно перезаписать метод paintComponent) и который должен реализовать прослушиватель мыши. Мое текущее решение, которое работает, состоит в том, чтобы иметь MapPanel в отдельном классе, реализующем MouseListener, но когда я показал это парню, который руководит моим курсом, на днях он, казалось, думал (у нас немного языковой барьер), это должно быть во внутреннем класс в ControllerWindow или, по крайней мере, MouseListener должен быть внутренним классом.Стандарты для использования внутренних классов для GUI?

Итак, мой вопрос заключается в том, что было бы стандартным решением здесь, поставить MouseListener во внутренний класс, JPanel в другом внутреннем классе или все еще в его отдельном классе? JPanel реализует MouseListener в одном внутреннем классе? И почему?

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

EDIT: очень упрощенная версия текущего кода ниже.

class ControllerWindow extends JFrame{ 
    ... 
    MapPanel drawPanel = new MapPanel(); 
    ... 
} 

и отдельный класс:

class MapPanel extends JPanel implements MouseListener{ 

    ... 

    public void paintComponent(Graphics g){ 
     ...//fillRects etc. 
    } 

    //MouseListener methods 
    public void mouseReleased(MouseEvent e){ 
     requestFocus(); 
     ... 
     repaint() 
     ... 
    } 
    public void mousePressed(MouseEvent e){} 
    public void mouseEntered(MouseEvent e){} 
    public void mouseExited(MouseEvent e){} 
    public void mouseClicked(MouseEvent e){} 
} 

Также это мог быть ситуацией, когда это было бы приемлемо, чтобы положить оба класса в одном файле? Я не предполагаю использовать MapPanel для чего угодно, кроме ControllerWindow.

+2

Стандартная практика для GUI-кода - это один большой шар грязи. –

+0

Не могли бы вы предоставить код? При необходимости упрощается. – amorfis

ответ

4

Я думаю, что это несколько произвольно, как вы это делаете (как комментировал Том Хотин, стандарты GUI = грязь), так как вы торгуете сложностью в количестве классов по сравнению со сложностью в одном классе. Если вы хотите создать код просто для демонстрации, один файл может быть проще всего. Если вы хотите, чтобы код, который вы собираетесь вводить в производство и модифицировать/поддерживать с течением времени, абстрагирование в разные классы почти наверняка будет таким, каким вы хотите.

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

С помощью MouseListener я был бы склонен включать его в MapPanel, если он обрабатывает события специально для этого компонента (то есть, если только MapPanel «знает», что означает «щелчок», он должен обрабатывать это нажмите). Я определенно не поместил бы его в ControllerWindow, так как тогда вы «утечка» детали реализации из MapPanel.(Единственный случай, о котором я могу думать: помимо вашего MapPanel у вас есть несколько типов панелей, которые все должны реагировать на клики одинаково, поэтому вместо того, чтобы внедрять в каждую панель, вы можете сделать ControllerWindow. Но даже тогда , Я не уверен, что код должен быть в ControllerWindow).

Независимо от того, является ли прослушиватель мыши MapPanel внутренней реализацией MouseListener, или реализует ли MapPanel его (как в вашем коде выше), вероятно, сводится к вопросу о том, какой стиль вы предпочитаете.

7

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

EDIT: Это особенно верно для классов, которые реализуют только один метод прослушивания. Возможно, менее верно для интерфейсов с несколькими методами, таких как MouseListener, поскольку класс, реализующий полный интерфейс, будет более подробным.

+2

Для таких интерфейсов, как 'MouseListener', существуют такие классы, как' MouseAdapter', которые позволяют вам переопределять только те методы, которые вам действительно интересны. – Bombe

+1

Yup, и это также может быть сделано как анонимный внутренний класс. Все побеждают. –

0

Из-за необходимости обработки нескольких событий необходимы анонимные внутренние классы. Анонимный класс может быть написан где угодно, как в классе, в методе, в аргументе. Поэтому воздерживаться от создания множества классов для каждого слушателя является анонимным.

1

Внутренний класс был бы лучше, если он имеет более простой синтаксис.

button1.click(function(event){ do something x... }); 
button2.click(function(event){ do something y... }); 
radio2.check (function(event){ do something z... }); 

java 7 может дать нам что-то подобное и изменить всю ситуацию. как и сейчас, использование множества анонимных внутренних классов может испортить код и сделать невозможным чтение. вы должны выбрать тот стиль, который сделает ваш код красивым и разборчивым.

0

Я нашел эту статью полезной: http://www.retrologic.com/innerclasses.doc3.html

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