2009-04-03 4 views
40

У меня есть класс, назовем его 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? Какова принятая практика?

+5

Лямбда любой :) – Matt

ответ

9

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

+0

Мой пример был несколько упрощен. В реальном коде он переопределяет 5 (не абстрактных) методов. –

+0

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

+1

согласился. Обычно я использую только анонимные классы, если они действительно простые. Не более одного определения маленькой функции, и я сделаю его нормальным внутренним классом (статическим, если это возможно). Просто проще читать этот путь. – Herms

0

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

+0

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

47

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

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

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

+3

+1 Хорошие моменты, но помните, что классы также могут быть определены внутри функций. Это ограничивает их сферу и может быть хорошим намеком на то, что у них есть очень локализованное использование. –

+3

Это очень веские причины не использовать анонимные классы. :) –

0

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

4

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

2

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

36

(счетчик пункт Daniel Lew)

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

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

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

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

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

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

+3

Это то, что я считаю уродливым в отношении анонимных внутренних классов. Вы читаете код, и внезапно появляется это определение класса smack в середине множества полей. –

+0

У меня всегда проблемы с выравниванием кода внутри анонимного класса. Как бы я ни старался, код по-прежнему выглядит уродливым: D – janetsmith

+0

Я согласен - я считаю код сложным для чтения/отладки, если есть много анонимных внутренних классов. Вместо того, чтобы объявлять анонимные внутренние классы в нескольких функциях (YUCK!), Я считаю, что гораздо лучше практиковать выделение разделов файла для названных внутренних классов, т. Е. В нижней части файла. –

3

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

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

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

1

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

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

7

Do the simplest thing that could possibly work: Используйте анонимный внутренний класс.

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

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

3

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

2

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

1

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

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

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

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

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

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

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

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

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

0

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

Смежные вопросы