Когда действительно полезно использовать вложенный класс Java? - PullRequest
1 голос
/ 12 марта 2019

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

Большое вам спасибо

Марко

Ответы [ 4 ]

3 голосов
/ 12 марта 2019

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

Например, Map.Entry: это запись в отображении. Это логически часть API Map, поэтому имеет смысл поместить его в Map.

Другим распространенным примером является Классы строителей : вы используете Builder для создания вещи, поэтому имеет смысл поместить ее внутрь этой вещи.

Это классы, которые вы действительно используете только в контексте использования внешних классов: иногда вы можете использовать Map.Entry сам по себе как некоторый класс пары; а иногда вы можете захотеть использовать Builder сам по себе, например, в качестве параметра метода, который помещает вещи в этот компоновщик, но на самом деле не выполняет саму конструкцию. Эти случаи, вероятно, редко бывают далеки от кода, который также использует внешний класс: вы все еще используете некоторый аспект API внешнего класса, поэтому они по-прежнему логически принадлежат этому API.

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

  • Это загромождает пространство имен. Если у вас есть классы Foo, Bar, Baz и т. Д., Наличие FooBuilder, BarBuilder, BazBuilder на верхнем уровне просто затрудняет просмотр "полезных" классов верхнего уровня.
    • Буферы протокола Google генерируют класс Builder для каждого типа сообщений. Учитывая количество буферов протокола, используемых в коде Google, этот беспорядок был бы слишком громоздким.
  • Вложенные классы имеют доступ к закрытым полям внешнего класса, что может помочь вам делать определенные вещи без ненужного раскрытия этих полей.
  • Вы можете ссылаться на вложенные классы, указав внешнее имя, например, Outer.Builder, вместо того, чтобы явно import some.pkg.OuterBuilder , а также import some.pkg.Outer. По общему признанию, я действительно не забочусь о количестве импорта, так как я просто держу их свернутыми в intellij.

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

1 голос
/ 12 марта 2019

Используется (также) для реализации Pattern Builder

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

0 голосов
/ 12 марта 2019

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

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

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

Наконец, есть анонимные внутренние классы, которые являются внутренними классами, у которых нет имени.

0 голосов
/ 12 марта 2019

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

abstract class Unit {
  private int HP;
  ....
  abstract class AI {
    abstract void heal();
  }
}

Позже я могу указать, какой тип устройства я проектирую:

class Infantry extends Unit {
  ...
  class InfantryAI extends AI {
    void heal() { this->HP++; }
  }
}

То, что вы видите, есть вторичный this - нестатические вложенные классы (иначе говоря, внутренние классы , такие как AI и InfantryAI) могут получить доступ к своим окружающим классам (Unit и Infantry) privateатрибуты как свои собственные, и это право доступа распространяется вниз по дереву наследования.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...