2011-01-10 1 views
16

Мне было интересно, почему Java была разработана без директивы friend, доступной на C++, чтобы обеспечить более точное управление тем, какие методы и переменные экземпляра доступны извне пакета, в котором был определен класс.Почему директива friend отсутствует на Java?

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

ответ

9

Вот несколько причин, с верхней части моей головы:

  • друга не требуется. Это удобно, но не обязательно
  • Друг поддерживает плохой дизайн. Если один класс требует доступа к другому другому, вы делаете это неправильно. (см. выше, удобно, не требуется).
  • друг разрушает инкапсуляцию. В принципе, все мои рядовые принадлежат мне, и этот парень там (мой друг).
+3

+1 для инкапсуляции :) – fresskoma

+20

-1 для инкапсуляции. Это распространенное недоразумение. Это просто неправильно. Хотя верно, что 'friend' * * может использоваться для разрыва инкапсуляции, так что другие функции могут быть использованы неправильно. Используется правильно, инкапсуляция 'friend' * увеличивает *, потому что она позволяет более мелкозернистый контроль доступа:' friend' заменяет использование 'public', а не' private'. [Техническое объяснение на C++ FAQ] (http://www.parashift.com/c++-faq-lite/friends.html#faq-14.2) (Тем не менее, я полностью удовлетворен видимостью пакета, но утверждая, что 'friend 'breaks encapsulation все еще не так.) –

+1

@ KonradRudolph Абсолютно согласен. Классы друзей необходимы для разделения проблем. Например, у меня есть класс «Сериализатор», который должен быть разрешен для записи в поля экземпляра, поэтому я предоставляю ему доступ для друзей. Другие классы не могут специально писать в поля и должны проходить через интерфейс, который я предоставляю. Единственный способ, которым вы можете это сделать в Java, - поместить все в один и тот же пакет. – crush

10

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

Я бы сказал, что чрезвычайно большое количество строк java в производстве в данный момент может подтвердить, что ключевое слово friend на самом деле не большая потеря :).

См. Ответ @ dwb по более конкретным причинам.

+3

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

+0

@irreputable Хорошее возвращение. Однако я был наполовину шучу :) –

+0

'friend' существует в виде видимости пакета. Это просто не так гибко в Java. – crush

2

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

+2

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

+0

Это не совсем так (вы не можете объявить класс как принадлежащий к пакету java. *, Например), и, кроме того, если кому-то действительно нужен такой взлом (помещение класса в org.apache.commons.logging, чтобы увидеть пакет-частные члены), они вполне могли бы использовать отражение и setVisible (true). Но я не говорю о хаках. В стандартном API Java интенсивно используется пакетно-частные члены. –

+2

@R. Bemrose: механизм видимости частного/защищенного/общедоступного/пакета не предназначен для обеспечения безопасности. Это функция программирования, предназначенная для инкапсуляции. – JeremyP

2

Просто, чтобы добавить к другим ответам:

Существует видимость пакет по умолчанию в Java. Итак, вы могли вызвать все классы в одном пакете соседей. В этом случае вы четко контролируете то, что вы показываете соседям - просто члены с видимостью пакета.

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

4

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

+0

Внутренний, но не частичный. – Vozzie

+0

@Vozzie, правда, но что это значит с «другом»? –

2

По моему мнению, какая-то особенность друга (не обязательно очень похожая на C++) была бы очень полезна в некоторых ситуациях на Java. В настоящее время у нас есть хакеры для доступа к частным/дефолтным пакетам для совместной работы между тесно связанными классами в одном пакете (например, String и StringBuffer), но это открывает частный интерфейс реализации вплоть до всего пакета. Между пакетами у нас есть зловещие хаки, которые вызывают целый ряд проблем.

Существует несколько дополнительных осложнений в этом на Java.C++ игнорирует ограничения доступа при разрешении перегрузок функций (и тому подобное) - если компиляция программы #define private public ничего не должна делать. Java (в основном) отбрасывает не доступных членов. Если нужно учитывать дружбу, то резолюция является более сложной и менее очевидной.

6

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

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

+1

Хотел бы я поддержать этот ответ 100х. Эта «дружба плохая» идеология опасна. – crush

+0

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

2

Полностью согласен с утверждением spaceghost в his answer

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

Мой пример прост - если класс A должен предоставить специальный интерфейс «другу» для класса B в java, мы должны поместить их в один и тот же пакет. Без исключений. В этом случае, если A является другом B и B является другом C, A должен быть другом C, что не всегда верно. Эта «транзитивность дружбы» разрушает инкапсуляцию больше, чем любые проблемы, к которым может привести дружба C++.