Java/Android: анонимные локальные классы против именованных классов

Я хотел бы спросить, какова хорошая практика использования анонимных классов по сравнению с именованными внутренними классами?

Я пишу приложение для Android, которое включает в себя множество элементов пользовательского интерфейса (кнопки, текстовые поля и т. Д.). Для многих из них мне нужны какие-то слушатели, поэтому в onCreate приложения у меня есть куча довольно небольших анонимных классов, таких как:

someButton.setOnClickListener(
    new View.OnClickListener() {
        public void onClick(View v) {
            // do something...
        }
    }
);

Каждый из таких анонимных классов имеет размер 5 - 20 строк - достаточно маленький и подходит для рекомендаций Java™ в книге "В двух словах":

В общем, вы должны рассмотреть возможность использования анонимного класса вместо локального класса, если:

  • У класса очень короткое тело.
  • Нужен только один экземпляр класса.
  • Класс используется сразу после его определения.
  • Название класса не делает ваш код легче для понимания.

Но проблема, IMO, в том, что onCreate становится достаточно большим, и код становится более сложным для чтения и понимания, если быстро взглянуть на него. Это все еще легко понять, но просто слишком велико.

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

6 ответов

Решение

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

Другой вариант - иметь

содержимое каждого onClick с помощью одного вызова функции, что сделает анонимные классы очень короткими. То есть:

someButton.setOnClickListener(
    new View.OnClickListener() {
        public void onClick(View v) {
            doSomeButtonClick();
        }
    }
);


private void doSomeButtonClick() {
  // do something
}

Рефакторинг onCreate() в отдельные методы, сгруппированные по общим функциям, так что у вас есть логические единицы. Если графический интерфейс пользователя сложный, он поможет вам позже.

РЕДАКТИРОВАТЬ:

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

Я делаю приложения для настольных компьютеров /Swing, но я думаю, что концепции совпадают.

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

Это дает мне несколько преимуществ:

  • Весь код обработки событий находится в одном классе.
  • Любое пересечение функциональности между событиями легко перехватывается и обрабатывается.
  • Любое состояние, которое затрагивается, может храниться и контролироваться в одном классе.
  • Весь код обработки событий отделен от кода компоновки компонента.
  • Слой View (Panel) ничего не знает о слое Controller.

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

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

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

У вас есть несколько преимуществ для размещения этих предметов в именованных классах.

Первый - тот, который вы упомянули - он сделает метод onCreate() более кратким и понятным.

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

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

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

Любые ответы, которые кто-либо даст вам на этот вопрос, основаны на их собственных субъективных показателях того, что такое "короткий" и сколько строк кода требуется, чтобы больше не быть "коротким".

Другие вопросы по тегам