Почему переменная частного члена может быть заменена экземпляром класса?
class TestClass
{
private string _privateString = "hello";
void ChangeData()
{
TestClass otherTestClass = new TestClass();
otherTestClass._privateString = "world";
}
}
Этот код компилируется в С#, и эквивалент работает в PHP, но может ли кто-нибудь объяснить причину, по которой otherTestClass._privateString
можно изменить здесь?
Я бы подумал, что экземпляр класса не сможет изменять переменную частного члена ни при каких обстоятельствах, и что попытка доступа к otherTestClass._privateString
даст ошибку "недосягаемый из-за уровня защиты".
Это не так, поэтому, почему создание экземпляра объекта внутри его собственного класса позволяет вам получить доступ к закрытым членам? И должно ли это, разве это не разрывает инкапсуляцию до такой степени? Или я пропущу что-то очевидное?
- (Я не спрашиваю, является ли вышеуказанный класс дизайном хорошей практикой, просто интересуется теорией, стоящей за ней.)
Изменить - Спасибо за ответы и комментарии. Чтобы уточнить, мне также интересно узнать, является ли возможность сделать это, считается положительной особенностью, или если это необходимый компромисс для лучшей проверки времени компиляции/ясности кода/потому что большинство других языков делает это так или иначе. Мне кажется, что в идеале компилятор предупредил бы вас об этом, но тогда я далек от разработчика языка. Любые примеры того, как именно это позволяет вам сделать что-то полезное (без нарушения инкапсуляции), которое в противном случае было бы трудным или невозможным, было бы здорово.
Ответы
Ответ 1
Частные члены доступны для любого кода в тексте программы этого класса (в том числе внутри вложенных типов). Это не имеет никакого отношения к тому экземпляру класса, с которым вы имеете дело.
Я не считаю, что это нарушает инкапсуляцию - API все еще отделен от реализации, но реализация "знает" о себе независимо от того, на каком экземпляре он смотрит.
Я считаю, что на некоторых других языках это не так, как работает доступность, но это определенно для С# и Java. (Java имеет несколько иные правила о том, что может получить доступ к закрытым членам, но переведенный код для того, что вы написали, все равно будет работать.)
Ответ 2
Это связано с тем, что С# обеспечивает конфиденциальность на уровне класса, а не конфиденциальность на уровне объекта.
В большинстве основных языков применяется одна и та же политика, например, С#, С++ и Java. Я думаю, что причина такова:
1), потому что разработчики привыкли к такой политике;
2), поскольку конфиденциальность на уровне объектов станет слишком утомительной в результате получения очень немногих преимуществ.