Аноним vs назвал внутренние классы? - лучшие практики?

У меня есть класс, назовем его LineGraph, который отображает линейный граф. Мне нужно подклассифицировать его, но производный класс используется только в одном месте и связан с классом, который его использует. Поэтому я использую внутренний класс.

Я вижу два способа сделать это:

Анонимный внутренний класс

public class Gui {
    LineGraph graph = new LineGraph() {
        // extra functionality here.
    };
}

Именованный внутренний класс

public class Gui {
    MyLineGraph graph = new MyLineGraph();

    private class MyLineGraph extends LineGraph {
        // extra functionality here.
    }
}

Я не поклонник анонимных внутренних классов, потому что, честно говоря, я просто думаю, что это выглядит действительно уродливо. Но в случае подкласса, который используется только в одном месте, это именованный внутренний класс overkill? Какова принятая практика?

Ответ 1

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

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

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

Ответ 2

(встречная точка для Даниэля Лью)

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

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

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

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

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

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

Ответ 3

Почему вам нужно подклассифицировать его? Если это просто переопределить существующий виртуальный метод, я думаю, что анонимный внутренний класс в порядке. Если вы добавляете дополнительные функции, я бы использовал именованный класс. Я бы сделал его вложенным классом (т.е. С модификатором static) - мне легче их рассуждать:)

Ответ 4

Простейшая вещь, которая могла бы работать: Используйте анонимный внутренний класс.

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

(Вы бы сделали то же самое с переменными - поставив их в наиболее специфическую область. Имеет смысл сделать то же самое с другими исходными ресурсами.)

Ответ 5

Анонимные внутренние классы трудно отлаживать в Eclipse (вот что я использую). Вы не сможете просмотреть значения переменных/значений впрыска, просто щелкнув правой кнопкой мыши.

Ответ 6

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

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

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

Ответ 7

Мое личное эмпирическое правило: если анонимный внутренний класс будет небольшим, придерживайтесь анонимного класса. Маленькое определение определяется как около 20-30 строк или меньше. Если он будет длиннее, он станет нечитаемым, по моему мнению, поэтому я ставлю его внутренним классом. Я помню, как однажды увидел анонимный внутренний класс 4000+.

Ответ 8

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

Ответ 9

У анонимных классов не может быть конструктора, так как они не имеют имени. Если вам нужно передать другие переменные, кроме тех, которые содержатся в конструкторе (-ах) класса, который вы расширяете, вы должны использовать (статический) внутренний класс. Иногда это можно преодолеть, используя конечные переменные в окружающем методе/коде, но это немного уродливое imho (и может привести к тому, что сказал Робин).

Ответ 10

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

Я видел код, в котором последний массив из 1 элемента используется для передачи данных обратно из вызова в анонимный внутренний класс. Внутри метода класса anon устанавливается единственный элемент, затем этот "результат" извлекается после завершения метода. Действительный, но уродливый код.

Ответ 11

Анонимные классы:

  • не может иметь ничего static в определении (статический класс, статическое поле, статический инициализатор и т.д.)
  • поля не могут быть проверены в Eclipse
  • не может использоваться как тип (Foo$1 myFoo=new Foo$1(){int x=0;} не работает)
  • не может быть найден с использованием имени класса в Eclipse (поиск Foo$1 не работает для меня)
  • нельзя использовать повторно

Однако анонимные классы могут иметь инициализатор, например {super.foo(finalVariable+this.bar);}

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

Я лично предпочитаю анонимные внутренние классы, если ограничения не применяются, потому что:

  • Я знаю, что любые дополнительные поля упоминаются только в определении класса.
  • Eclipse может легко конвертировать их в вложенные классы.
  • Мне не нужно копировать переменные, которые я хочу использовать. Я могу просто объявить их окончательными и ссылаться на них. Это особенно полезно, когда у меня много параметров.
  • Код, который взаимодействует, находится близко друг к другу.

Ответ 12

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

Ответ 13

Я думаю, что это вопрос вкуса. Я предпочитаю использовать анонимные классы для Functors. Но в вашем случае я бы использовал внутренний класс, так как я думаю, что вы упакуете больше, чем просто несколько строк кода, возможно, больше, чем просто метод. И это будет подчеркивать тот факт, что он добавляет функциональность в суперкласс, помещая его внутри класса, а не скрывая где-нибудь в методе. Плюс, кто знает, может быть, когда-нибудь вам понадобится подкласс else where. Это, конечно, зависит от того, насколько вы знаете о том, как ваше программное обеспечение будет развиваться. Кроме этого, просто переверните монету.:)

Ответ 14

Просто сегодня эта дискуссия состоялась с моим коллегой и копалась вокруг популярного мнения.

Я согласен с TofuBeer. Если ваш код имеет более 2 строк, он, вероятно, не является "одноразовым" и может быть использован повторно. Если вы создаете форму с использованием шаблона MVC, у вас может быть 20 управляемых элементов на странице, а не загромождать представление с помощью тонны классов анонимайа (черт возьми, ваш взгляд, вероятно, был создан с использованием GUI-конструктора, и код был автоматически создан редактируя источник, даже не вариант), вы, скорее всего, будете кормить каждый элемент контроллером. Вы можете встраивать внутренние классы в контроллер, чтобы обрабатывать каждый отдельный интерфейс обработчика/прослушивателя, который требуется вашему представлению. Это очень хорошо организовывает код, особенно если у вас есть соглашение о том, что ваш класс обработчика должен быть назван с использованием имени элемента GUI (например, backButtonHandler для backButtonElement). Это очень сработало для нас, и мы написали инструмент автоматической регистрации (при регистрации контроллера на представлении представление ищет внутренние классы с использованием имени элемента и использует их для обработчика на каждом именованном элементе). Это было бы невозможно с анонимными классами и делает контроллер намного более пригодным для повторного использования.

TL;DR: если есть сомнения, напишите названный внутренний класс. Вы никогда не узнаете, хочет ли кто-нибудь повторно использовать ваш код когда-нибудь (если это не две строки, тогда вам нужно задаться вопросом, разве этот код пахнет?). Кодекс, который хорошо организован, имеет гораздо более высокие выгоды в долгосрочной перспективе, особенно когда ваш проект находится в обслуживании.

Ответ 15

С анонимными внутренними классами мы не можем изменять состояние включенных членов класса. Они должны быть объявлены окончательными.