Серия Азбука
SCOPE – что в имени твоем? Часть 2.
В первой части были рассмотрены области видимости переменных Visual FoxPro. Кроме переменных вы можете наложить ограничение по видимости на свойства и методы элементов управления и форм. В вашем распоряжении три области видимости: Public, Protected и Hidden. При работе с классом в визуальном конструкторе класса, вы можете добавить новые свойства и методы, выбрав пункт "New Property…" или "New Method…" в меню Class (Класс). В этом случае в диалоговом окне ввода нового свойства или метода вам предоставляется перечень областей видимости, из которого вы можете выбрать требуемую.

Рис.1 Диалоговое окно ввода новых свойств и методов
Кроме того, этот диалог вы можете вызвать из диалогового окна "Edit Property", которое вызывается из меню "Class ® Edit Property/Method…". В этом диалоговом окне вы можете вызвать показанный выше диалог, щелкнув по командной кнопке "New… "(Новые…) или изменить области видимости уже имеющихся свойств или методов, выбрав требуемый в списке Visibility.

Рис.2 Диалоговое окно "Edit Property"
Разумеется, при программном создания класса с помощью команды DEFINE CLASS вы также можете указать для свойств и методов области видимости Protected или Hidden с помощью ключевых слов PROTECTED и HIDDEN. По умолчанию, вновь добавляемые в классы свойства и методы имеют область видимости Public.
Если для свойства или метода вы указали область видимости Public, то это означает, что вы можете обращаться к таким свойствам и устанавливать их новые значения или вызывать такие методы из кода других классов и процедур. Иначе обстоят дела со свойствами и методами для которых указаны области видимости Protected или Hidden.
Прежде всего разберемся, чем отличаются эти две области.
Область видимости Protected
Если вы указали для свойства или метода класса область видимости Protected, то это означает, что к такому свойству и методу могут обращаться только члены этого класса и субклассов на его основе. Посмотрим, как это работает.
Откройте проект "js_scope2". В диспетчере проекта перейдите на закладку классы и откройте на редактирование класс "user_admin", описанный в библиотеке класса
"js_scop2.vcx" и просмотрите его добавленные свойства и методы на закладке "Favorites". Программный код этого класса приведен в листинге 1. В этом классе определена переменная "cvc_Role", для которой установлена область видимости Protected. Кроме этой переменной в классе определены четыре метода: get_UserRole, set_UserRole, udp_GetUserRole и udp_SetUserRole. Для методов get_UserRole и set_UserRole также, как и для переменной cvc_Role в качестве областей видимости выбраны Protected. Для методов udp_GetUserRole и udp_SetUserRole в качестве областей видимости выбраны Pubic.
Листинг 1. Код класса "user_admin"
**
*-- Class: user_admin (c:\foxclub_journal\2008november\js_scope2\js_scope2.vcx)
*-- ParentClass: custom
*-- BaseClass: custom
DEFINE CLASS user_admin AS custom
PROTECTED cvc_role
cvc_role = "Global"
*-- XML Metadata for customizable properties
_memberdata = [<VFPData>
<memberdata name="cvc_role" type="property"
display="cvc_Role" favorites="True"/>
<memberdata name="set_userrole" type="method"
display="set_UserRole" favorites="True"/>
<memberdata name="get_userrole"
type="method" favorites="True" display="get_UserRole"/>
<memberdata name="udp_getuserrole" type="method" display="udp_GetUserRole"
favorites="True"/>
<memberdata name="udp_setuserrole" type="method"
display="udp_SetUserRole" favorites="True"/>
</VFPData>]
Name = "user_admin"
*-- Sets value of the protected property with name "cvc_Admin".
PROTECTED PROCEDURE set_userrole
Lparameters lpcNewValue
This. cvc_Role=lpcNewValue
=Messagebox(;
[The new value of the property with name "cvc_Role" is:]+;
CHR(13)+;
this. cvc_Role,;
0+64,;
"Protected property value";
)
ENDPROC
*-- Gets value of the protected property with name "cvc_Role".
PROTECTED PROCEDURE get_userrole
=Messagebox(;
[Current value of the property with name "cvc_Role" is:]+;
CHR(13)+;
this. cvc_Role,;
0+64,;
"Protected property value";
)
ENDPROC
*-- Calls the protected method get_UserRole
PROCEDURE udp_getuserrole
This. get_UserRole()
ENDPROC
*-- Calls the protected method set_UserRole
PROCEDURE udp_setuserrole
LPARAMETERS lpcNewValueForRole
This. set_UserRole(lpcNewValueForRole)
ENDPROC
ENDDEFINE
*
*-- EndDefine: user_admin
**
Так как при создании класса для свойства cvc_Role была установлена область видимости Protected, то обращение к этому свойству экземпляра класса извне, например, из командного окна должно вызвать ошибку. Это же справедливо и для методов get_UserRole и set_UserRole. Чтобы обратиться к этому свойству или к указанным методам извне, необходимо использовать методы этого класса, для которых область видимости установлена как Public. Убедитесь в этом, для чего закройте конструктор класса и в командной окне напечатайте и исполните приведенные ниже команды, подставив в первой строке ваш путь к проекту :
SET CLASSLIB TO путь_к_каталогу_проекта\js_scope2.vcx additive
oUA=CreateObject("user_admin")
? oUA. cvc_Role
oUA. get_UserRole()
oUA. set_UserRole("Supervisor")
Три последние строки вызовут ошибку с номером 1734 (Property "name" is not found).
Сообщение об ошибке для третьей строки кода приведено на рис.3

Далее выполните две приведенные ниже команды:
oUA. udp_GetUserRole()
oUA. udp_SetUserRole("Supervisor")
В результате исполнения этих двух команд будут выведены два сообщения, показанные на рисунках ниже:

Рис.4. Результат вызова метода udp_GetUserRole()

Рис.5. Результат вызова метода udp_SetUserRole()
В библотеку класса js_scope2 добавлен также класс "user_subadmin", созданный на основе класса "user_admin", к методам которого добавлены еще два с областью видимости Public и с именами " udp_GetProtectedValue" и "udp_SetProtectedValue". Программный код этого класса приведен в листинге 2. Так как свойство "cvc_Role" в родительском класса этого класса было определено с областью видимости Protected, то вызов этих методов соответственно отобразит текущее значение этого свойства или установит и отобразит новое значение, так как обращение к защищенному свойству допускается из методов субклассов класса, в котором защищенное свойство определено.
Листинг 2. Программный код класса "user_subadmin".
**
*-- Class: user_subadmin (c:\foxclub_journal\2008november\js_scope2\js_scope2.vcx)
*-- ParentClass: user_admin (c:\foxclub_journal\2008november\js_scope2\js_scope2.vcx)
*-- BaseClass: custom
DEFINE CLASS user_subadmin AS user_admin
_memberdata = [<VFPData>
<memberdata name="cvc_role" type="property" display="cvc_Role" favorites="True"/>
<memberdata name="set_userrole" type="method" display="set_UserRole"/>
<memberdata name="get_userrole" type="method" favorites="True"
display="get_UserRole"/>
<memberdata name="udp_getuserrole" type="method" display="udp_GetUserRole"/>
<memberdata name="udp_setuserrole" type="method" display="udp_SetUserRole"/>
<memberdata name="udp_setprotectedvalue" type="method"
display="udp_SetProtectedValue" favorites="True"/>
<memberdata name="udp_getprotectedvalue" type="method"
display="udp_GetProtectedValue" favorites="True"/>
</VFPData>]
Name = "user_subadmin"
PROCEDURE udp_setprotectedvalue
Lparameters lpcNewValue
This. cvc_Role=lpcNewValue
=Messagebox(;
[The new value of the protected property with name "cvc_Role" is:]+;
CHR(13)+;
this. cvc_Role,;
0+64,;
"Protected property value accessed from subclass";
)
ENDPROC
PROCEDURE udp_getprotectedvalue
=Messagebox(;
[Current value of the protected property with name "cvc_Role" is:]+;
CHR(13)+;
this. cvc_Role,;
0+64,;
"Protected property value accessed from subclass";
)
ENDPROC
ENDDEFINE
*
*-- EndDefine: user_subadmin
**
Выполните в командном окне Visual FoxPro приведенные ниже команды:
oUA=CREATEOBJECT("user_subadmin")
oUA. udp_GetProtectedValue
oUA. udp_SetProtectedValue("Superadmin")
В результате исполнения этих команд вы получите сообщения о текущем значении свойства cvc_Role, а также о вновь установленном значении этого свойства.
Область видимости Hidden
Если вы указали для свойства или метода область видимости Hidden, то к такому свойству или методу могут обращаться только члены класса. Вы не сможете обратиться к этому свойству из субкласса, то есть, если в субклассе вы создали методы, которые получают или устанавливают значение этого свойства, то вызов этих методов приведет к генерации ошибки 1734. Убедитесь в этом сами. Откройте на редактирование класс "user_admin". Вызовите диалоговое окно редактирования свойств и методов класса (см. рис.2) и измените область видимости свойства cvc_Role на Hidden.
Исполните повторно приведенные выше строки кода. Теперь при вызове методов udp_GetProtectedValue и oUA. udp_SetProtectedValue() вы получите сообщение об ошибке 1734. Однако вы сможете обратиться к этому свойству через методы, пусть даже и защищенные, в родительском классе.
Добавьте в класс "user_subadmin" новый метод с областью видимости Public и с именем "udp_GetRoleViaParentMethod". Код этого метода должен содержать только одну строку:
this. get_UserRole
Если теперь вы создадите заново экземпляр этого класса и вызовите вновь определенный метод "udp_GetRoleViaParentMethod", вы получите сообщение о текущем значении переменной.
Какова практическая польза, которая может быть получена при использовании областей видимости Protected и Hidden? Об этом чуть позже.


