Почему директива friend отсутствует в Java?
-
09-10-2019 - |
Вопрос
Мне было интересно, почему Java была разработана без friend
директива, доступная в C ++ для обеспечения более точного контроля над тем, какие методы и переменные экземпляра доступны извне пакета, в котором был определен класс.
Я не вижу ни практической причины, ни какого-либо конкретного недостатка, это кажется просто проблемой дизайна, но чем-то, что не создало бы никаких проблем, если бы было добавлено в язык.
Решение
Вот несколько причин, которые приходят мне в голову:
- друг не требуется.Это удобно, но не обязательно
- друг поддерживает плохой дизайн.Если одному классу требуется доступ друга к другому, вы делаете это неправильно.(смотрите выше, удобно, но не обязательно).
- друг нарушает инкапсуляцию.По сути, все мои интимные места принадлежат мне и вон тому парню (моему другу).
Другие советы
В целом, я думаю, что это произошло из-за дополнительной когнитивной сложности и небольшого числа случаев, в которых это приводит к улучшению.
Я бы сказал, что чрезвычайно огромное количество строк java, находящихся в производстве на данный момент, может свидетельствовать о том, что friend
ключевое слово на самом деле не является большой потерей :).
Пожалуйста, ознакомьтесь с ответом @dwb по некоторым более конкретным причинам.
Только очень наивный и неопытный программист стал бы выступать против друзей.Конечно, им можно злоупотреблять, как и общедоступными данными, но такая возможность предусмотрена.
Вопреки распространенному мнению, приведено много примеров, в частности для инфраструктурных возможностей, когда доступ к друзьям приводит к ЛУЧШЕМУ дизайну, а не к худшему.Инкапсуляция часто нарушается, когда метод ПРИНУДИТЕЛЬНО становится общедоступным, когда этого действительно не должно быть, но у нас не остается выбора, потому что Java не поддерживает friends.
В дополнение к вышеупомянутой видимости пакета, Java также предлагает внутренние и анонимные классы, которые не только являются друзьями по умолчанию, но и автоматически имеют ссылку на содержащий класс.Поскольку создание таких вспомогательных классов, вероятно, является единственным разумным способом использования friend
в C ++ Java это не нужно, поскольку у нее есть другой механизм для этого.Итераторы - очень хороший пример этого.
Почему бы просто не подумать, что Java требует совместного расположения дружественных классов?Приватная видимость пакета позволяет всем пользователям из одного и того же пакета получить доступ к этим участникам.Таким образом, вы не ограничены только явно заявленными друзьями, но и разрешаете любому (существующему или будущему) другу изменять некоторые участники, которые специально предназначены для этой цели (но не ваши личные данные).Вы по-прежнему можете полностью полагаться на инкапсуляцию.
Просто чтобы добавить к другим ответам:
Существует значение по умолчанию видимость упаковки на языке Java.Итак, вы мог бы вызовите все классы в одном пакете neighbors.В этом случае у вас есть явный контроль над тем, что вы показываете соседям - только членам с видимостью пакета.
Итак, на самом деле это не друг, но может быть похож.И да, это тоже приводит к плохому дизайну...
На мой взгляд, какая-то функция friend (не обязательно очень похожая на C ++) была бы очень полезна в некоторых ситуациях на Java.В настоящее время у нас есть хаки доступа к закрытому пакету / доступу по умолчанию, позволяющие осуществлять совместную работу между тесно связанными классами в одном пакете (String
и StringBuffer
например), но это открывает частный интерфейс реализации для всего пакета.Между пакетами у нас есть злые взломы отражения, которые вызывают целый ряд проблем.
Существует небольшая дополнительная сложность в том, как сделать это на Java.C ++ игнорирует ограничения доступа при устранении перегрузок функций (и подобных им) - если программа компилируется #define private public
не должен ничего делать.Java (в основном) отбрасывает недоступные элементы.Если необходимо принимать во внимание дружбу, то решение более сложное и менее очевидное.
Полностью согласен с заявлением spaceghost в его ответ
Вопреки распространенному мнению, приведено много примеров, в частности для инфраструктурных возможностей, когда доступ к друзьям приводит к ЛУЧШЕМУ дизайну, а не к худшему.
Мой пример прост - если класс A должен предоставить специальный "дружественный" интерфейс классу B на java, мы должны поместить их в один и тот же пакет.Никаких исключений.В этом случае, если A является другом B, а B - другом C, A должен быть другом C, что не всегда верно.Эта "транзитивность дружбы" нарушает инкапсуляцию больше, чем любые проблемы, к которым может привести дружба с C ++.