Чтобы уточнить, о чем я спрашиваю,
public class A{
private/*or public*/ B b;
}
против
public class A{
private/*or public*/ class B{
....
}
}
Я могу определенно подумать о некоторых причинах, чтобы использовать одну или другую, но то, что я действительно хотел бы видеть, - это убедительные примеры, которые показывают, что плюсы и минусы не просто академические.
object-oriented-design
class-design
EpsilonVector
источник
источник
Ответы:
Они обычно используются, когда класс является внутренней деталью реализации другого класса, а не частью его внешнего интерфейса. Я в основном видел их как классы только для данных, которые делают внутренние структуры данных более чистыми в языках, которые не имеют отдельного синтаксиса для структур в стиле c. Они также полезны иногда для сильно настраиваемых, производных от одного метода объектов, таких как обработчики событий или рабочие потоки.
источник
Предположим, вы строите дерево, список, график и так далее. Почему вы должны выставлять внутренние детали узла или ячейки внешнему миру?
Любой, кто использует график или список, должен полагаться только на его интерфейс, а не на его реализацию, поскольку вы можете захотеть изменить его однажды в будущем (например, с реализации на основе массива на указатель), а клиенты, использующие ваш структура данных ( каждая из них ) должна будет изменить свой код, чтобы привести его в соответствие с новой реализацией.
Вместо этого, инкапсуляция реализации узла или ячейки в закрытом внутреннем классе дает вам свободу изменять реализацию в любое время, когда вам необходимо, без необходимости принудительно корректировать клиентский код, пока остается интерфейс вашей структуры данных. нетронутым.
Сокрытие деталей реализации вашей структуры данных также приводит к преимуществам безопасности, потому что если вы хотите распространять свой класс, вы сделаете доступным только файл интерфейса вместе с скомпилированным файлом реализации, и никто не узнает, используете ли вы на самом деле массивы или указатели. для вашей реализации, таким образом защищая ваше приложение от какой-либо эксплуатации или, по крайней мере, знаний из-за невозможности неправильного использования или проверки вашего кода. В дополнение к практическим вопросам, пожалуйста, не стоит недооценивать тот факт, что это чрезвычайно элегантное решение в таких случаях.
источник
На мой взгляд, честный полицейский должен использовать внутренние классы для классов, которые кратко используются в классе, чтобы разрешить конкретную задачу.
Например, если вам нужно связать список данных, состоящий из двух не связанных классов:
Если ваш внутренний класс используется другим классом, вы должны поместить его отдельно. Если ваш внутренний класс содержит какую-либо логику, вы должны поместить ее отдельно.
По сути, я думаю, что они отлично подходят для устранения дыр в ваших объектах данных, но их сложно поддерживать, если они действительно содержат логику, так как вам нужно будет знать, где их искать, если вам нужно ее изменить.
источник
tuple.ItemX
делает код неясным.Внутренние классы в некоторых языках (например, Java) имеют связь с объектом своего содержащего класса и могут использовать их члены, не определяя их. Когда это возможно, это яснее, чем переопределять их, используя другие языковые средства.
Вложенные классы на другом языке (например, C ++) не имеют такой связи. Вы просто используете обзор и контроль доступности, предоставляемые классом.
источник
Я избегаю внутренних классов в Java, потому что горячая замена не работает при наличии внутренних классов. Я ненавижу это, потому что я действительно ненавижу компрометировать код для таких соображений, но эти перезапуски Tomcat складываются.
источник
Одним из применений для закрытого статического внутреннего класса является шаблон Memo. Вы помещаете все данные, которые необходимо запомнить, в закрытый класс и возвращаете их из некоторой функции как объект. Никто снаружи не может (без отражения, десериализации, проверки памяти ...) изучить его / изменить его, но он может вернуть его вашему классу, и он может восстановить его состояние.
источник
Одной из причин использования закрытого внутреннего класса может быть то, что используемый вами API требует наследования от определенного класса, но вы не хотите экспортировать знания этого класса пользователям вашего внешнего класса. Например:
В этом do_my_async_op требует, чтобы объект типа callback был передан ему. Этот обратный вызов имеет открытую подпись функции-члена, которую использует API.
Когда do_op () вызывается из external_class, он использует экземпляр закрытого внутреннего класса, который наследует от требуемого класса обратного вызова вместо указателя на себя. Внешний класс имеет ссылку на внешний класс для простой цели - переадресации обратного вызова в частную функцию-член do_callback внешнего класса .
Преимущество этого заключается в том, что вы уверены, что никто другой не сможет вызвать публичную функцию-член «fire ()».
источник
По словам Джона Скита в C # in Depth, использование вложенного класса было единственным способом реализовать полностью ленивый потокобезопасный синглтон (см. Пятую версию) (до .NET 4).
источник
Закрытые и внутренние классы используются для повышения уровня инкапсуляции и скрытия деталей реализации.
В C ++, в дополнение к закрытому классу, та же концепция может быть реализована путем реализации анонимного пространства имен класса cpp. Это прекрасно скрывает / приватизирует детали реализации.
Это та же идея, что и у внутреннего или частного класса, но на еще большем уровне инкапсуляции, поскольку она полностью невидима вне модуля компиляции файла. Ничего из этого не появляется в заголовочном файле или внешне не видно в объявлении класса.
источник