Ответ 1
Это "нормально". Private
члены являются закрытыми для класса, а не для конкретного экземпляра.
Во время очистки некоторого кода, написанного сегодня кем-то другим, я изменил модификатор доступа с Public
до Private
на переменную class/member/field. Я ожидал длинный список ошибок компилятора, которые я использую для "рефакторинга/доработки/пересмотра" кода, который использовал эту переменную. Представьте мое удивление, когда я не получил никаких ошибок. После просмотра выясняется, что другой экземпляр класса может получить доступ к закрытым членам другого экземпляра, объявленного в классе. Полностью исключен.
Это нормально? Я кодировал в .NET с самого начала и никогда не сталкивался с этой проблемой и не читал об этом. Я, возможно, наткнулся на него раньше, но только "смутно заметил" и двинулся дальше. Может ли кто-нибудь объяснить это поведение мне? Я хотел бы знать, почему я могу это сделать. Пожалуйста, объясните, не просто скажите мне правило. Я делаю что-то неправильно? Я нашел это поведение как в С#, так и в VB.NET. Код, похоже, использует возможность доступа к закрытым переменным. Недостатком является то, что программист создал большую пластину спагетти.
С уважением,
Class Jack
Private _int As Integer
End Class
Class Foo
Public Property Value() As Integer
Get
Return _int
End Get
Set(ByVal value As Integer)
_int = value * 2
End Set
End Property
Private _int As Integer
Private _foo As Foo
Private _jack As Jack
Private _fred As Fred
Public Sub SetPrivate()
_foo = New Foo
_foo.Value = 4 'what you would expect to do because _int is private
_foo._int = 3 'TOTALLY UNEXPECTED
_jack = New Jack
'_jack._int = 3 'expected compile error
_fred = New Fred
'_fred._int = 3 'expected compile error
End Sub
Private Class Fred
Private _int As Integer
End Class
End Class
Это "нормально". Private
члены являются закрытыми для класса, а не для конкретного экземпляра.
Ты сказал:
Пожалуйста, объясните, не просто скажите мне правило.
Ну, вот мои два цента.
Как я вижу, предпосылка частных членов класса заключается в том, что класс может внутренне осознавать свою собственную реализацию, не подвергая эту реализацию внешнему миру. Таким образом, один экземпляр класса отлично способен понять, как реализуется другой экземпляр того же класса; поэтому он не ограничивается использованием этих знаний о реализации.
Что касается экземпляров, которые манипулируют друг другом, я соглашусь, что это несколько необычно. Но возьмите, например, статические методы построения. Не могли бы вы также ограничить их доступ к частным членам экземпляров? Если это так, вы сделали много полезного кода невозможным. Если нет, неясно, почему статические методы должны иметь доступ к закрытым членам, но методы экземпляров не должны.
Другими словами, слово "private" в ООП не предназначено для передачи идеи личной неприкосновенности, как у людей, скрывающихся друг от друга. Скорее, подумайте о классе как о клубе "только члены", где есть определенные способы делать то, о чем знают только члены клуба.
Проблема доступа - это то, где код обращается к частным членам, а не о том, к чему он обращается.
У вас есть доступ к полю _foo._int
в определении класса Foo
, но не за его пределами.
Еще может удивить вас тем, что следующее расширение для вложенного класса Fred
также является законным.
Private Class Fred
Private _int As Integer
Private Sub Blah(ByVal foo As Foo)
foo._int = 9
End Sub
End Class
Это ожидаемое поведение. Вложенные классы могут обращаться к закрытым членам класса контейнера.