Почему экземпляр класса может получить доступ к закрытым полям другого экземпляра своего собственного типа?

Экземпляр класса в Java может обращаться к закрытым полям другого экземпляра своего собственного типа, например, в следующем списке:

public class Foo {
  private int secret;
  public void bar(final Foo foo) {
    foo.secret = 100;
  }
}

Каким будет аргумент для такой семантики (при разработке языка)?

Ответы

Ответ 1

Хорошо, сначала вы должны спросить: "Почему у вас есть частные поля?"

Частные поля предназначены в первую очередь для инкапсуляции: пользователю класса не нужно знать внутренности реализации этого класса. Фактически, они не должны знать, потому что, если они полагаются на эти особенности, тогда разработчик будет вынужден поддерживать их или нарушать совместимость. Другими словами, он защищает пользователя и конструктора класса:

  • пользователь защищен от изменений в реализации, нарушающих ее код
  • разработчик защищен от необходимости сохранять функции реализации без изменений навсегда

Но класс не должен быть защищен от самого себя; ему не нужно беспокоиться о случае, когда один бит его кода изменяется, но другой бит (который использует первый бит) не может измениться. Обратная совместимость не вызывает беспокойства, потому что класс разработан как единый атомный кусок кода. Другими словами, ни одна из вышеупомянутых защит не требуется.

Поскольку нет необходимости защищать поля, и поскольку часто бывает необходимо их видеть (например, для сравнения, если два объекта равны), они видны внутри класса.

Ответ 2

Поле private предназначено для того, чтобы сообщить другим программистам не вмешиваться в него.

Предположительно, все, работающие в одном классе, знают, что делают все переменные. Поле private не скрывает ваш собственный код от вас, только снаружи.

Ответ 3

Вы можете копировать/сравнивать значения без дополнительных геттеров и изменять поле без сеттеров. Не знаю, каким образом в JVM такие простые методы-вызовы оптимизируются каким-либо образом, но если нет, то это приводит к некоторым накладным расходам.

Можно подумать, что сохранение такого "открытого" доступа может привести к некоторым проблемам безопасности, но при реализации класса вы предоставляете все методы для управления этими переменными. Никто не может изменить их из классов, расширяющих этот класс. По сути, они по-прежнему закрыты - доступны только из вашего кода.

Имейте в виду, что логически классу часто приходится выполнять одно задание. Может быть полезно разделить некоторую информацию и облегчить доступ, особенно в случаях, когда производится большое количество экземпляров. Когда вы имеете дело с случаями, когда требуется больше контроля, всегда можно использовать модификатор доступа к пакетам (который больше "private" в некотором смысле...) или лимит экземпляра экземпляра с шаблоном singleton/factory.