Доступ к частному полю другого объекта в том же классе
class Person
{
private BankAccount account;
Person(BankAccount account)
{
this.account = account;
}
public Person someMethod(Person person)
{
//Why accessing private field is possible?
BankAccount a = person.account;
}
}
Пожалуйста, забудьте о дизайне. Я знаю, что OOP указывает, что частные объекты являются частными для класса. Мой вопрос заключается в том, почему OOP был разработан таким образом, чтобы частные поля имели доступ на уровне класса и не на уровне уровня доступа?
Ответы
Ответ 1
Мне также немного любопытно с ответом.
Наиболее удовлетворительный ответ, который я нахожу, от Артемикса в другом посте здесь (я переименовываю AClass в класс Person): Почему вместо уровня объекта используются модификаторы доступа на уровне класса?
Частный модификатор применяет принцип инкапсуляции.
Идея состоит в том, что "внешний мир" не должен вносить изменения во внутренние процессы Person, потому что реализация Person может со временем меняться (и вам придется изменить весь внешний мир, чтобы исправить различия в реализации - что почти невозможно).
Когда экземпляр Person обращается к внутренним объектам другого экземпляра Person, вы можете быть уверены, что оба экземпляра всегда знают детали реализации Person. Если логика внутренних процессов к Человеку изменилась - все, что вам нужно сделать, это изменить код человека.
РЕДАКТИРОВАТЬ: Пожалуйста, проголосуйте за ответ Артемикс. Я просто копирую это.
Ответ 2
См. Спецификация языка Java, раздел 6.6.1. Определение доступности
В нем указано
В противном случае, если член или конструктор объявлен private
, тогда доступ разрешен тогда и только тогда, когда он встречается в теле класс верхнего уровня (§7.6), который включает объявление члена или конструктор.
Нажмите ссылку выше для получения более подробной информации. Поэтому ответ: потому что Джеймс Гослинг и другие авторы Java решили, что это так.
Ответ 3
Хороший вопрос. Похоже, что модификатор доступа к уровню объекта еще больше выполнит принцип инкапсуляции.
Но на самом деле это наоборот. Возьмем пример. Предположим, вы хотите глубоко скопировать объект в конструктор, если вы не можете получить доступ к частным членам этого объекта. Тогда единственным возможным способом является добавление некоторых публичных аксессуаров ко всем частным членам. Это сделает ваши объекты голыми ко всем остальным частям системы.
Таким образом, инкапсуляция не означает закрытие всего остального мира. Это означает быть избирательным, о котором вы хотите быть открытым.
Ответ 4
Это работает, потому что вы находитесь в class Person
- классу разрешено выступывать внутри него собственный тип класса. Это действительно помогает, когда вы хотите написать конструктор копирования, например:
class A
{
private:
int x;
int y;
public:
A(int a, int b) x(a), y(b) {}
A(A a) { x = a.x; y = y.x; }
};
Или, если мы хотим написать operator+
и operator-
для нашего большого класса чисел.
Ответ 5
Поскольку модификатор private
доступа отображает его только в классе. Этот метод все еще находится в классе.
Ответ 6
Ключевое слово private означает, что поле или метод скрыты от представления любого другого класса. Не на текущем объекте класса.
Ответ 7
поле private
доступно в классе/объекте, в котором объявлено поле. Он является приватным для других классов/объектов за пределами того, в котором он находится.
Ответ 8
Вы пытаетесь сказать, что ни один объект не должен иметь доступ к этому частному атрибуту любым возможным способом? в чем смысл этого атрибута? В некотором роде этот атрибут способствует состоянию объекта, но это состояние не известно никому другому.
Ответ 9
С концепцией отражения в Java возможно изменение полей и методов privateates
Модифицированные методы и возможности использования Ref Refcion en Java
Ответ 10
Прежде всего, мы должны понять, что все, что нам нужно сделать, - это следовать принципам oops, поэтому инкапсуляция означает, что обертывать данные в пакете (т.е. классе) и представлять все данные как объекты и легкодоступные., поэтому, если мы сделаем поле не приватным, а
он обращался к нему безразлично. и это приводит к плохой паратике.
Ответ 11
Только мои 2 цента на вопрос о том, почему семантика частной видимости в Java является уровнем класса, а не уровнем объекта.
Я бы сказал, что здесь удобство. Фактически, частная видимость на уровне объекта вынудила бы подвергать методы другим классам (например, в том же пакете) в сценарии, проиллюстрированном OP.
По правде говоря, я не смог ни придумать, ни найти пример, показывающий, что видимость на уровне класса-класса (например, предлагаемая Java) создает любые проблемы по сравнению с видимостью на уровне объекта-частного.
Тем не менее, языки программирования с более тонкой системой политик видимости могут позволить как видимость объектов на уровне объекта, так и уровне класса.
Например Eiffel предлагает выборочный экспорт: вы можете экспортировать любую функцию класса в любой класс по вашему выбору, от {NONE} (объект-частный) до {ANY} (эквивалент общедоступной, а также по умолчанию), до {PERSON} (класс-частный, см. пример OP) для определенных групп классов {PERSON, BANK}.
Также интересно заметить, что в Eiffel вам не нужно делать атрибут private и писать геттер, чтобы другие классы не могли присваивать ему. Публичные атрибуты в Eiffel по умолчанию доступны в режиме только для чтения, поэтому вам не нужен геттер, чтобы вернуть свое значение.
Конечно, для установки атрибута вам все равно нужен сеттер, но вы можете скрыть его, указав его как "назначающий" для этого атрибута. Это позволяет вам, если хотите, использовать более удобный оператор присваивания вместо вызова setter.
Ответ 12
Частный доступ в java - это доступ к классу, как вы писали.
Scala также имеет частный объект в виде private[this]
и другие различные способы, описанные здесь http://alvinalexander.com/scala/how-to-control-scala-method-scope-object-private-package
Скорее всего, доступ к частному классу в java считался достаточным и был синхронизирован с тем, что С++ имел в тот момент.
Я предполагаю, что этого было достаточно в java, потому что класс был написан в одном файле, поэтому автор мог решить получить доступ к членам между разными экземплярами, если он действительно этого хотел. В scala вы можете наследовать поведение из нескольких признаков, и это может изменить игру.