Почему в Java отсутствует директива friend?
Мне было интересно, почему Java была разработана без директивы friend
, которая доступна на С++, чтобы позволить более тонкий контроль над тем, какие методы и переменные экземпляра доступны извне пакета, в котором был определен класс.
Я не вижу никакой практической причины или какого-либо конкретного недостатка, это просто проблема дизайна, но что-то, что не создавало бы проблем, если бы было добавлено к языку.
Ответы
Ответ 1
Вот несколько причин от головы:
- Друг не требуется. Это удобно, но не требуется.
- Друг поддерживает плохой дизайн. Если один класс требует доступа к другому другому, вы делаете это неправильно. (см. выше, удобно, не требуется).
- друг разрушает инкапсуляцию. В принципе, все мои рядовые принадлежат мне, и этот парень там (мой друг).
Ответ 2
В целом, я думаю, что это связано с добавленной когнитивной сложностью и небольшим количеством случаев, когда оно создает улучшение.
Я бы сказал, что чрезвычайно большое количество строк java в производстве на данный момент может подтвердить, что ключевое слово friend
на самом деле не большая потеря:).
Пожалуйста, см. @dwb ответ на некоторые более конкретные причины.
Ответ 3
Только очень наивный и неопытный программист будет выступать против друзей. Конечно, это может быть неправильно использовано, но так же могут публичные данные, но эта возможность предоставляется.
Вопреки распространенному мнению, здесь много случаев, в частности, для инфраструктурных возможностей, когда доступ к друзьям ведет к более легкому дизайну, а не к худшему дизайну. Инкапсуляция часто нарушается, когда метод FORCED становится общедоступным, когда его действительно не должно быть, но у нас нет выбора, потому что Java не поддерживает друзей.
Ответ 4
В дополнение к вышеупомянутой видимости пакета Java также предлагает внутренние и анонимные классы, которые по умолчанию являются не только друзьями, но также автоматически ссылаются на содержащийся класс. Поскольку создание таких вспомогательных классов, вероятно, является единственным разумным способом использования friend
в С++, Java не нуждается в нем, поскольку для этого есть другой механизм. Итераторы - очень хороший пример этого.
Ответ 5
Почему бы просто не подумать, что Java требует, чтобы классы друзей были совместно расположены? Пакет-конфиденциальная видимость позволяет всем из одного пакета получать доступ к этим членам. Таким образом, вы ограничены не только явно объявленными друзьями, но и позволяете любому (существующему или будущему) другу изменять некоторые члены, специально предназначенные для этой цели (но не ваши личные вещи). Вы все еще можете полностью полагаться на инкапсуляцию.
Ответ 6
Просто добавьте к другим ответам:
В Java есть видимость пакета по умолчанию. Таким образом, вы можете вызвать все классы в одном сосете пакетов. В этом случае у вас есть явный контроль над тем, что вы показываете соседям - просто члены с видимостью пакета.
Итак, это не совсем друг, но может быть похожим. И да, это тоже приводит к плохому дизайну...
Ответ 7
По моему мнению, какая-то особенность друга (не обязательно очень похожая на С++) была бы очень полезна в некоторых ситуациях на Java. В настоящее время у нас есть хакеры для доступа к частным/дефолтным пакетам для совместной работы между тесно связанными классами в одном пакете (например, String
и StringBuffer
), но это открывает частный интерфейс реализации для всего пакета. Между пакетами у нас есть злые рефлексивные хаки, которые вызывают целый ряд проблем.
В Java есть несколько дополнительных осложнений. С++ игнорирует ограничения доступа при разрешении перегрузок функций (и подобных) - если компиляция программы #define private public
не должна ничего делать. Java (в основном) отбрасывает не доступных членов. Если нужно учитывать дружбу, то резолюция является более сложной и менее очевидной.
Ответ 8
Полностью согласен с косвенным выражением в его ответе
Вопреки распространенному мнению, здесь много случаев, в частности, для инфраструктурных возможностей, когда доступ к друзьям приводит к более легкому дизайну, а не к худшему дизайну.
Мой пример прост - если класс A должен предоставить специальный интерфейс "friend" для класса B в java, мы должны поместить их в один и тот же пакет. Без исключений. В этом случае, если A является другом B и B является другом C, A должен быть другом C, что не всегда верно. Эта "транзитивность дружбы" разрушает инкапсуляцию больше, чем любые проблемы, к которым может привести дружба С++.