26.09.2013

Приватные (private) секции видимости класса

Хотелось бы начать свой блог с освещения вопроса, с которым я часто сталкиваюсь при изучении кода, написанного начинающими программистами. Как известно, при создании класса в нашем распоряжении есть так называемые уровни инкапсуляции, в народе более известные как области видимости (хотя на самом деле понятие "область видимости" немного иное и касается переменных). И если с уровнями public, protected и published все достаточно ясно, они ведут себя в точности как и называются, то уровень private не так и прост. Как переводится private? Частный, личный, тайный, закрытый. Многие начинающие программисты так и относятся к методам, описанным в этой секции. А что мы умеем на самом деле? Справка Delphi XE5 (актуальная на сегодня) нам говорит следующее:
A private member is invisible outside of the unit or program where its class is declared. In other words, a private method cannot be called from another module, and a private field or property cannot be read or written to from another module. By placing related class declarations in the same module, you can give the classes access to one another’s private members without making those members more widely accessible. For a member to be visible only inside its class, it needs to be declared strict private.
В общем все написано как и есть. Но вот беда, люди начинают изучать программирование совершенно не зная английского, а если и знают, то на недостаточном уровне что бы свободно читать справку (чего таить, я сам таким был). Что они делают? Они ищут русскоязычную информацию. А русскоязычные справочники в большинстве своем говорят нам следующее:
Директива Private начинает раздел данных (полей) и подпрограмм (методы) класса, которые являются частными (внутренними) для этого класса. Это - жизненно важная часть Объектно-ориентированной концепции, в которой класс рассматривается как черный ящик - то, что используется внутри не уместно для внешнего использования. Указанные в частном (Private) разделе данные и подпрограммы используются другими подпрограммами только данного класса.
Если частные данные нуждаются во внешнем доступе, то свойство public (или published) предоставят данный доступ.
Частные (Private) данные и подпрограммы не доступны даже потомкам класса, чтобы обеспечить этот доступ вы должны использовать Protected. Защищенные (Protected) данные и методы внешне невидимы, но доступны для всех классов в иерархии.
Данный текст был взят с русскоязычного справочника функций и процедур как пример, но подобное я встречаю практически во всех русскоязычных обучающий материалах.

Что мы имеем в итоге?
Русскоязычные начинающие программисты неверно трактуют секцию private, считая ее полностью защищенной от вызовов за пределами методов класса. Что бы людям, которые плохо знают английский и изучают программирование по русскоязычным материалам, стало понятно о чем я пишу, давайте переведем официальную справку на русский (перевод мой личный и не дословный, а отражающий суть написанного):
Все что указано в private секции класса невидимо за пределами модуля или программы, где этот класс объявлен. Другими словами, метод, объявленный в private секции не может быть вызван из другого модуля, поля и свойства, объявленные в private секции, не могут быть прочитаны или установлены из другого модуля. Размещая объявление классов в одном модуле, Вы можете иметь доступ к private секции всех классов этого модуля, не делая эту секцию широко доступной. Для объявления секции, видимой только внутри данного класса, необходимо использовать strict private.
Думаю теперь видны отличия русскоязычных справочников и официальной информации. Если русскоязычные справочники делают акцент на то, что private секция полностью изолирована от внешнего мира, то в официальной информации четко сказано, что изоляция происходит только за пределами модуля, а все что внутри модуля может иметь полный доступ к private секции. Так же озвучено, что если нужна действительно полная изоляция (именно та, а которой пишется в русскоязычных справочниках), то нужно применять strict private.

Чего так получилось? 
Для начала стоит заметить, что объявление секции как strict private появилось только в Delphi 2007, а большинство книг и справочников на русском языке написаны в далекие времена господствования Delphi 7. Т.е. когда писались эти книги и справочники, еще не было введено конструкции strict private, авторы не задавались вопросом: "А в чем же разница?". Еще одной причиной может быть перевод самого слова private и недопонимание авторов русскоязычных материалов всех нюансов и тонкостей языка Delphi.

Какие из всего этого можно сделать выводы?
  1. Доверяйте только официальным источникам! Даже если Вы не знаете английский, воспользуйтесь сервисами он-лайн перевода, суть вам будет понятна.
  2. Старайтесь объявлять каждый класс в отдельном модуле (для версий Delphi ниже 2007) или пользоваться конструкцией strict private. Так вы сможете гарантировать что private секция действительно будет приватной и никто посторонний не имеет к ней доступа.
  3. Используйте информацию, которая касается именно той версии Delphi, с которой Вы работаете. Использование устаревших данных может быть опасно и ввести в заблуждение.
О том, почему нужно серьезно относится к скрытию методов, полей и свойств, я напишу в следующих публикациях.

Комментариев нет:

Отправить комментарий