Джава. Вложенные классы со статическим членом. Как мы можем обойти это? - PullRequest
1 голос
/ 24 ноября 2011

Мой вопрос: известно, что вложенный класс не может иметь статический член (только если класс не описан как static ). Но иногда нам нужно это иметь.

Пример: у нас есть библиотека . У него книг (мы будем рассматривать книги как неотъемлемую часть библиотеки, я просто не могу догадаться о другом примере) . В классе Библиотека Я должен описать вложенный закрытый класс Книга . Вложено, потому что Book существует только в библиотеке (как я уже описывал ранее). Частный, потому что мы хотим разрешить создание книги за пределами библиотеки. Я хочу иметь счетчик всех книг, хранящихся во всех библиотеках. В простой ситуации у меня должен быть статический счетчик, но там я не могу. И я не могу описать Book как статический класс, потому что Book принадлежит Библиотеке.

Ответы [ 7 ]

1 голос
/ 24 ноября 2011

Причина, по которой вы не можете иметь статический член в Book, заключается в том, что Book является нестатическим членом Library.Таким образом, класс Book имеет неявную ссылку на экземпляр класса включения (экземпляр Library).У вас есть несколько вариантов:

  1. Сделать класс Book статическим.
  2. Вместо этого оставить статический счетчик в классе Library.
  3. Make Bookсовершенно отдельный класс от Library в целом.Экземпляр библиотеки может хранить счетчик того, сколько книг в ней хранится.

Лично я считаю, что №3 - лучший вариант.Book не следует заставлять находиться в библиотеке, его также следует разрешать для CoffeeTable.: Р

1 голос
/ 24 ноября 2011

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

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

Таким образом, только библиотека может использовать класс.

, например

package com.company.library;

private class Book {
}
1 голос
/ 24 ноября 2011

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

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

Помните, что одним из пунктов ОО является указание объектам делать что-то для вас .

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

0 голосов
/ 24 ноября 2011

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

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

0 голосов
/ 24 ноября 2011

Это то, что вы имеете в виду?

class Library {

    private static long allBooksInAllLibraries;

    private class Book {

        private Book() {
            // this should be synchronized if threads are involved
            allBooksInAllLibraries += 1;
        }
    }
 }
0 голосов
/ 24 ноября 2011

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

В общем случае, для создания вложенного класса используется только класс: используется внешним классом.Например, Library может иметь CardCatalog, который является внутренним для Библиотеки, и который никогда не взаимодействует напрямую с пользователями Библиотеки.Даже тогда, это будет часто менее запутанным, если вы сделаете связь между ними более явной, сделав CardCatalog статическим внутренним классом и передав ему экземпляр Library в своем конструкторе.Помимо всего прочего, он будет более тестируемым.

0 голосов
/ 24 ноября 2011

Я могу понять проблему, о которой вы упомянули, но скажите мне кое-что. Отображение библиотеки в книгу - один ко многим. Это одна библиотека может иметь много книг. Так что, на мой взгляд, это может быть лучше обработано, если у вас есть отдельный класс библиотеки и отдельный класс книг. Вы можете связать arrayList с классом Library типа Book, например:

Библиотека классов {private ArrayList <.Books>; }

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

...