Delphi 3. Библиотека программиста

Читаем, чтобы записывать?


На самом деле происходит следующее: в большинстве случаев действительно применима простая модель, описанная выше. Однако, если свойство является потомком TPersistent (например, TBitmap или TFont), происходит нечто странное. Для потомков TPersistent метод write вызывается в тех случаях, когда свойство задается в режиме конструирования или изменяется в режиме выполнения— но не при создании и загрузке компонента из DFM-потока его формы. Вместо этого runtime-библиотека вызывает метод read данного свойства, чтобы получить указатель на присвоенный ему private-объект, а затем использует полученный указатель для вызова метода чтения из потока. То есть при загрузке компонента метод write не вызывается!

Разумеется, в большинстве случаев это несущественно — свойство все равно загружается и получает в режиме выполнения то же значение, что было задано в режиме конструирования. Тем не менее в некоторых ситуациях это все же может отразиться на вашей программе.

Во-первых, метод read никогда не должен возвращать Nil. Мысль о том, чтобы отложить создание private-объекта до того момента, когда метод write предоставит копируемое значение, выглядит вполне разумно. К сожалению, код загрузки компонентов Delphi недостаточно умен — он просто не замечает, что у него нет объекта TPersistent, которому нужно дать команду загрузиться из потока. Поэтому если метод read возвращает Nil, то при загрузке компонента происходит GPF (General Protection Fault, ошибка защиты). Кстати, именно это обстоятельство привлекло мое внимание, хотя признаюсь, что я не сразу разобрался в сути происходящего.

Во-вторых, не стоит использовать метод write для того, чтобы извлекать информацию из private-объекта свойства и сохранять ее в других runtime-полях вашего компонента. Метод write вызывается при непосредственном задании свойства в режиме конструирования или выполнения, но не при косвенном задании этого свойства, происходящем в момент загрузки компонента. Если воспользоваться методом write для обновления внутреннего состояния компонента, загрузка будет работать неверно.



Содержание раздела