Классы. Статические и динамические сущности: различия между версиями
(не показано 5 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
Каждый класс должен иметь декларацию класса и | ==Классы== | ||
Имплементация класса содержит собственно реализацию предикатов (клаузы). | Каждый класс должен иметь декларацию класса и имплементацию. | ||
'''Декларация класса''' содержит набор объявлений констант, доменов, предикатов, видимых извне. | |||
'''Имплементация класса''' содержит | |||
*собственно реализацию предикатов (клаузы), объявленных в декларации, | |||
*декларации констант, | |||
*декларации и реализации предикатов, используемых в клаузах, | |||
*декларации фактов. | |||
*Факты и предикаты, объявленные в имплементации класса, извне не видны. | |||
'''Cтатический класс''' - класс не способный порождать объекты (экземпляры или точные копии). | '''Cтатический класс''' - класс не способный порождать объекты (экземпляры или точные копии). | ||
Все предикаты и разделы фактов статического класса существуют | Все предикаты и разделы фактов статического класса существуют в единственном экземпляре во всем проекте. | ||
в единственном экземпляре во всем проекте. | |||
'''Динамический класс''' - класс, способный порождать объекты (экземпляры или точные копии), | '''Динамический класс''' - класс, способный порождать объекты (экземпляры или точные копии), | ||
Каждый экземпляр динамического класса содержит свою копию предиката и свою копию раздела фактов. | Динамические классы могут содержать как статические, так и динамические предикаты, а также статические и динамические факты. | ||
Каждый экземпляр динамического класса содержит свою копию динамического предиката и свою копию динамического раздела фактов. | |||
Создание объекта (экземпляра или копии класса) осуществляется вызовом предиката-конструктора. Как правило, это предикат-функция ''new()'', но может быть и любой другой, объявленный как конструктор в разделе ''constructors'' декларации класса. | Создание объекта (экземпляра или копии класса) осуществляется вызовом предиката-конструктора. Как правило, это предикат-функция ''new()'', но может быть и любой другой, объявленный как конструктор в разделе ''constructors'' декларации класса. | ||
Статический класс - это класс, не имеющий интерфейса. | '''Статический класс''' - это класс, не имеющий интерфейса. | ||
Или, что то же самое, - если класс не имеет инерфейса, то он - статический, | Или, что то же самое, - если класс не имеет инерфейса, то он - статический, | ||
Если класс имеет интерфейс - то он - динамический. | Если класс имеет интерфейс - то он - динамический. | ||
Статические классы | ==Статические классы== | ||
Например, класс staticClass является статическим классом. | Например, класс ''staticClass'' является статическим классом. | ||
<vip> | <vip> | ||
class staticClass | class staticClass | ||
Строка 27: | Строка 37: | ||
Чтобы что-то делать, добавим в этот класс декларации предикатов и клаузы. | Чтобы что-то делать, добавим в этот класс декларации предикатов и клаузы. | ||
<vip> | <vip>class staticClass | ||
class staticClass | predicates | ||
visibleStaticPred:(). | visibleStaticPred:(). | ||
end class staticClass | end class staticClass | ||
implement staticClass | implement staticClass | ||
clauses | |||
visibleStaticPred():- | visibleStaticPred():- | ||
... | ... | ||
Строка 40: | Строка 49: | ||
... | ... | ||
class predicates | |||
invisibleStaticPred:(). | invisibleStaticPred:(). | ||
clauses | |||
invisibleStaticPred():- | invisibleStaticPred():- | ||
... | ... | ||
Строка 49: | Строка 58: | ||
Обращения к предикатам этого класса записываются как | Обращения к предикатам этого класса записываются как | ||
<vip> | <vip>... | ||
staticClass::staticVisiblePred(), | |||
... | |||
</vip> | </vip> | ||
(существенно использования именно :: для обращения к статической сущности) | (существенно использования именно '''::''' для обращения к статической сущности) | ||
Здесь предикат ''invisibleStaticPred'' является предикатом, объявленным внутри имплементации, и только внутри этой имплементации может быть вызван. | Здесь предикат ''invisibleStaticPred'' является предикатом, объявленным внутри имплементации, и только внутри этой имплементации может быть вызван. | ||
То есть предикаты, объявленные в декларации класса являются заведомо всегда статическими предикатами, а раздел объявлений предикатов внутри имплементации статического класса всегда должен имет вид | То есть предикаты, объявленные в декларации класса, являются заведомо всегда статическими предикатами, а раздел объявлений предикатов внутри имплементации статического класса всегда должен имет вид class predicates | ||
Если попробовать создать экземпляр класса ''staticClass'' с помощью вызова конструктора ''new()'' | |||
class predicates | <vip>... | ||
staticClass::new(), | |||
...</vip> | |||
Если попробовать создать экземпляр класса ''staticClass'' с помощью вызова конструктора ''new()'' | |||
<vip> ... | |||
</vip> | |||
то это не пропустит компилятор. | то это не пропустит компилятор. | ||
Таким образом, статические классы - это просто модули проекта. | Таким образом, статические классы - это просто модули проекта. | ||
Проект, построенный только на модулях (статических классах) - не имеет никакого отношения к объекто-ориентированной концепции программирования. | Проект, построенный только на модулях (статических классах) - не имеет никакого отношения к объекто-ориентированной концепции программирования. | ||
Динамические классы | ==Динамические классы== | ||
Например, класс ''dynamicClass'' является динамическим классом, что определяется | Например, класс ''dynamicClass'' является динамическим классом, что определяется | ||
конструкцией ''dynamicClass:justInterface''. | конструкцией ''dynamicClass:justInterface''. | ||
<vip> | <vip>class dynamicClass:justInterface | ||
class dynamicClass:justInterface | |||
end class dynamicClass | end class dynamicClass | ||
Строка 87: | Строка 84: | ||
interface justInterface | interface justInterface | ||
end interface justInterface | end interface justInterface</vip> | ||
</vip> | |||
Опять-таки, синтаксически все правильно, но практически бесполезно. | Опять-таки, синтаксически все правильно, но практически бесполезно. | ||
Теперь добавим какие-нибудь полезности и вынесем вперед декларацию интерфейса. | Теперь добавим какие-нибудь полезности и вынесем вперед декларацию интерфейса. | ||
<vip>interface justInterface | <vip>interface justInterface | ||
predicates | |||
visibleDynamicPred:(). | visibleDynamicPred:(). | ||
end interface justInterface | end interface justInterface | ||
class dynamicClass:justInterface | class dynamicClass:justInterface | ||
predicates | |||
visibleStaticPred:(). | visibleStaticPred:(). | ||
end class dynamicClass | end class dynamicClass | ||
implement dynamicClass | implement dynamicClass | ||
clauses | |||
visibleStaticPred():- | visibleStaticPred():- | ||
... | ... | ||
Строка 108: | Строка 104: | ||
... | ... | ||
clauses | |||
visibleDynamicPred():- | visibleDynamicPred():- | ||
... | ... | ||
Строка 114: | Строка 110: | ||
... | ... | ||
class predicates | |||
invisibleStaticPred:(). | invisibleStaticPred:(). | ||
clauses | |||
invisibleStaticPred():- | invisibleStaticPred():- | ||
... | ... | ||
predicates | |||
invisibleDynamicPred:(). | invisibleDynamicPred:(). | ||
clauses | |||
invisibleDynamicPred():- | invisibleDynamicPred():- | ||
... | ... | ||
Строка 128: | Строка 124: | ||
end implement dynamicClass | end implement dynamicClass | ||
</vip> | </vip> | ||
Здесь мы имеем четыре предиката, которые имеют различные динамические особенности. | Здесь мы имеем четыре предиката, которые имеют различные динамические особенности. | ||
''visibleDynamicPred'' - динамический предикат, принадлежащий интерфесу ''justInterface'', видимый извне. | ''visibleDynamicPred'' - динамический предикат, принадлежащий интерфесу ''justInterface'', видимый извне. | ||
''visibleStaticPred'' - статический предикат, видимый извне. | ''visibleStaticPred'' - статический предикат, видимый извне. | ||
''invisibleStaticPred'' - статический предикат, определенный в имплементации класса ''dynamicClass'', невидимый извне. | ''invisibleStaticPred'' - статический предикат, определенный в имплементации класса ''dynamicClass'', невидимый извне. | ||
''invisibleDynamicPred'' - динамический предикат, определенный в имплементации класса ''dynamicClass'', невидимый извне. | ''invisibleDynamicPred'' - динамический предикат, определенный в имплементации класса ''dynamicClass'', невидимый извне. | ||
К такому классу можно обратиться как к статическому | |||
<vip>... | |||
dynamicClass::visibleStaticPred(), | |||
...</vip> | |||
но нельзя так: | |||
<vip>... | |||
dynamicClass::visibleDynamicPred(), | |||
...</vip> | |||
Чтобы вызвать предикат ''visibleDynamicPred()'', необходимо с помощью конструктора создать экземпляр класса и обратиться к этому экземпляру: | |||
<vip>... | |||
ЭкземплярDynamicClass=dynamicClass::new(), | |||
ЭкземплярDynamicClass:visibleDynamicPred(), | |||
...</vip> | |||
Примечания: | |||
* Конструктор ''new()'' является предопределенным конструктором, объявление которого не требуется, если в имплементации нет для него клауза; | |||
* В обращении к экземпляру класса (объекту) используется разделитель ':' (а не '::', как этого требует обращение к статической сущности). | |||
==Факты== | |||
Факты декларируются и могут быть использованы в клаузах предикатов только в имплементации класса. | |||
Нельзя объявить факты в одном классе и пытаться использовать обращение к ним в другом классе. | |||
В статических классах факты должны быть объявлены только как статические. | |||
<vip>implement example | |||
... | |||
class facts | |||
myFact_F:(string,string). | |||
... | |||
end implement example</vip> | |||
В имплементациях динамических классов факты могут быть объявлены либо как статические, либо как динамические: | |||
<vip>class example1:example1interface | |||
predicates | |||
запомнитьГород:(string Город). | |||
запомнитьИмяАдрес:(string Имя, string Адрес). | |||
получитьГород:()->string Город. | |||
получитьИмяАдрес:(string Имя, string Адрес). | |||
end class example1 | |||
implement example1 | |||
... | |||
class facts | |||
город_V:string Город. | |||
... | |||
facts | |||
имяАдрес_F:(string Адрес, string Имя). | |||
clauses | |||
запомнитьГород(Город):- | |||
город_V:=Город. | |||
... | |||
clauses | |||
запомнитьИмяАдрес(Имя,Адрес):- | |||
assert(имяАдрес_F:(Адрес,Имя)). | |||
clauses | |||
получитьГород(город_V). | |||
... | |||
clauses | |||
получитьИмяАдрес(Имя,Адрес):- | |||
имяАдрес_F(Адрес,Имя), | |||
!, | |||
... | ... | ||
end implement example1 | |||
</vip> | |||
В приведенном примере класса ''example1'' факт ''город_V'' является статическим, а факты ''имяАдрес_F(...)'' являются динамическими, | |||
что определяется разницей в имени раздела ''class facts'' и просто ''facts''. | |||
Поскольку статическая сущность любого класса всего одна, а динамическая - по одной на каждый экземпляр - то и в нашем примере запрос ''получитьГород()'', переданный любому экземпляру, вернет один и тот же результат, а запрос ''получитьИмяАдрес(...)'' вернет для каждого экземпляра свое значение. | |||
===Особенности использования фактов-переменных=== | |||
В примере выше использовался факт-переменная ''город_V'', особенностью которого является то, что такой факт всегда один и он сам несет значение терма, объявленного в декларации. | |||
<vip> | |||
class facts | |||
город_V:string Город.</vip> | |||
Здесь факт ''город_V'' имеет строковое значение. Возможны значения любых объявленных доменов, например | |||
<vip>domains | |||
мойДомен=персона(string Имя,unsigned Возраст). | |||
class facts | |||
персона_V:мойДомен.</vip> | |||
В отличие от обычных фактов, факт-переменная всегда существует и должен иметь начальное значение. | |||
Начальное значение факту-переменной можно задать при объявлении | |||
<vip>domains | |||
мойДомен=персона(string Имя,unsigned Возраст). | |||
class facts | |||
персона_V:мойДомен:=персона("Старик",80). | |||
город_V:string:="НеИзвестен". | |||
</vip> | </vip> | ||
В динамических классах начальное значение вместо декларации можно задать в клаузе конструктора | |||
<vip>implement dynamicClass | |||
domains | |||
мойДомен=персона(string Имя,unsigned Возраст). | |||
class facts | |||
персона_V:мойДомен. | |||
clauses | |||
new():- | |||
персона_V:=персона("Старик",80), | |||
... | |||
end implement dynamicClass</vip> | |||
Бывает, что конкретное начальное значение установить невозможно по смыслу реализации. | |||
Тогда начальное значение может быть установлено как "неустановленное". | |||
<vip>class facts | |||
город_V:string:=erroneous.</vip> | |||
где ''erroneous'' - ключевое слово языка. Факт со значением erroneous не может быть использован (точнее: при попытке его использования будет выдана соответствующая ошибка), можно только проверить является ли значение факта неустановленным с помощью детерминированного предиката ''isErroneous(...)'' | |||
<vip>implement dynamicClass | |||
domains | |||
мойДомен=персона(string Имя,unsigned Возраст). | |||
class facts | |||
город_V:string:=erroneous. | |||
персона_V:мойДомен. | |||
clauses | |||
new():- | |||
персона_V:=персона("Старик",80), | |||
... | |||
clauses | |||
... | |||
isErroneous(город_V), | |||
... | |||
end implement dynamicClass</vip> | |||
С учетом сказанного наш пример | |||
<vip>class facts | |||
город_V:string Город.</vip> | |||
на этапе компиляции выдаст ошибку, поскольку статический факт не инициализирован при объявлении. | |||
==Константы и домены== | |||
Константы и домены могут объявляться везде - в декларациях классов, интерфейсов и в имплементациях. По своей сущности они, естественно, имеют статический характер. | |||
Объявления, сделанные в имплементации, видимы только внутри этой же имплементации. | |||
Объявления констант и доменов, сделанные в декларации класса или интерфейса, являются глобальными. | |||
Конкретное использование осуществляется путем добавления префикса декларации соответствующего класса или интерфейса в формате | |||
''<имя декларации класса или интерфейса>::<имя домена или константы>''. | |||
<vip> | ==Взаимоотношени статических и динамических сущностей== | ||
Клаузы предикатов, объявленных статическими, не могут обращаться к динамическим сущностям (предикатам и фактам). | |||
То есть нельзя так: | |||
<vip>implement dynamicClass | |||
clauses | |||
staticPred():- | |||
... | ... | ||
dynamicPred(), | |||
... | ... | ||
</vip> | end implement dynamicClass</vip> | ||
Клаузы предикатов, объявленных динамическими, такого ограничения не имеют. | |||
Как статические так и динамические факты могут хранить указатели на динамические предикаты и экземпляры классов. | |||
[[Категория:VipLanguage]] | [[Категория:VipLanguage]] |
Текущая версия на 09:43, 8 августа 2008
Классы
Каждый класс должен иметь декларацию класса и имплементацию.
Декларация класса содержит набор объявлений констант, доменов, предикатов, видимых извне.
Имплементация класса содержит
- собственно реализацию предикатов (клаузы), объявленных в декларации,
- декларации констант,
- декларации и реализации предикатов, используемых в клаузах,
- декларации фактов.
- Факты и предикаты, объявленные в имплементации класса, извне не видны.
Cтатический класс - класс не способный порождать объекты (экземпляры или точные копии). Все предикаты и разделы фактов статического класса существуют в единственном экземпляре во всем проекте.
Динамический класс - класс, способный порождать объекты (экземпляры или точные копии), Динамические классы могут содержать как статические, так и динамические предикаты, а также статические и динамические факты. Каждый экземпляр динамического класса содержит свою копию динамического предиката и свою копию динамического раздела фактов. Создание объекта (экземпляра или копии класса) осуществляется вызовом предиката-конструктора. Как правило, это предикат-функция new(), но может быть и любой другой, объявленный как конструктор в разделе constructors декларации класса.
Статический класс - это класс, не имеющий интерфейса. Или, что то же самое, - если класс не имеет инерфейса, то он - статический,
Если класс имеет интерфейс - то он - динамический.
Статические классы
Например, класс staticClass является статическим классом.
class staticClass end class staticClass implement staticClass end implement staticClass
но этот класс ничего не способен делать. Чтобы что-то делать, добавим в этот класс декларации предикатов и клаузы.
class staticClass predicates visibleStaticPred:(). end class staticClass implement staticClass clauses visibleStaticPred():- ... invisibleStaticPred(), ... class predicates invisibleStaticPred:(). clauses invisibleStaticPred():- ... end implement staticClass
Обращения к предикатам этого класса записываются как
... staticClass::staticVisiblePred(), ...
(существенно использования именно :: для обращения к статической сущности)
Здесь предикат invisibleStaticPred является предикатом, объявленным внутри имплементации, и только внутри этой имплементации может быть вызван. То есть предикаты, объявленные в декларации класса, являются заведомо всегда статическими предикатами, а раздел объявлений предикатов внутри имплементации статического класса всегда должен имет вид class predicates Если попробовать создать экземпляр класса staticClass с помощью вызова конструктора new()
... staticClass::new(), ...
то это не пропустит компилятор. Таким образом, статические классы - это просто модули проекта. Проект, построенный только на модулях (статических классах) - не имеет никакого отношения к объекто-ориентированной концепции программирования.
Динамические классы
Например, класс dynamicClass является динамическим классом, что определяется конструкцией dynamicClass:justInterface.
class dynamicClass:justInterface end class dynamicClass implement dynamicClass end implement dynamicClass interface justInterface end interface justInterface
Опять-таки, синтаксически все правильно, но практически бесполезно. Теперь добавим какие-нибудь полезности и вынесем вперед декларацию интерфейса.
interface justInterface predicates visibleDynamicPred:(). end interface justInterface class dynamicClass:justInterface predicates visibleStaticPred:(). end class dynamicClass implement dynamicClass clauses visibleStaticPred():- ... invisibleStaticPred(), ... clauses visibleDynamicPred():- ... invisibleStaticPred(), ... class predicates invisibleStaticPred:(). clauses invisibleStaticPred():- ... predicates invisibleDynamicPred:(). clauses invisibleDynamicPred():- ... end implement dynamicClass
Здесь мы имеем четыре предиката, которые имеют различные динамические особенности. visibleDynamicPred - динамический предикат, принадлежащий интерфесу justInterface, видимый извне. visibleStaticPred - статический предикат, видимый извне. invisibleStaticPred - статический предикат, определенный в имплементации класса dynamicClass, невидимый извне. invisibleDynamicPred - динамический предикат, определенный в имплементации класса dynamicClass, невидимый извне. К такому классу можно обратиться как к статическому
... dynamicClass::visibleStaticPred(), ...
но нельзя так:
... dynamicClass::visibleDynamicPred(), ...
Чтобы вызвать предикат visibleDynamicPred(), необходимо с помощью конструктора создать экземпляр класса и обратиться к этому экземпляру:
... ЭкземплярDynamicClass=dynamicClass::new(), ЭкземплярDynamicClass:visibleDynamicPred(), ...
Примечания:
- Конструктор new() является предопределенным конструктором, объявление которого не требуется, если в имплементации нет для него клауза;
- В обращении к экземпляру класса (объекту) используется разделитель ':' (а не '::', как этого требует обращение к статической сущности).
Факты
Факты декларируются и могут быть использованы в клаузах предикатов только в имплементации класса. Нельзя объявить факты в одном классе и пытаться использовать обращение к ним в другом классе. В статических классах факты должны быть объявлены только как статические.
implement example ... class facts myFact_F:(string,string). ... end implement example
В имплементациях динамических классов факты могут быть объявлены либо как статические, либо как динамические:
class example1:example1interface predicates запомнитьГород:(string Город). запомнитьИмяАдрес:(string Имя, string Адрес). получитьГород:()->string Город. получитьИмяАдрес:(string Имя, string Адрес). end class example1 implement example1 ... class facts город_V:string Город. ... facts имяАдрес_F:(string Адрес, string Имя). clauses запомнитьГород(Город):- город_V:=Город. ... clauses запомнитьИмяАдрес(Имя,Адрес):- assert(имяАдрес_F:(Адрес,Имя)). clauses получитьГород(город_V). ... clauses получитьИмяАдрес(Имя,Адрес):- имяАдрес_F(Адрес,Имя), !, ... end implement example1
В приведенном примере класса example1 факт город_V является статическим, а факты имяАдрес_F(...) являются динамическими, что определяется разницей в имени раздела class facts и просто facts. Поскольку статическая сущность любого класса всего одна, а динамическая - по одной на каждый экземпляр - то и в нашем примере запрос получитьГород(), переданный любому экземпляру, вернет один и тот же результат, а запрос получитьИмяАдрес(...) вернет для каждого экземпляра свое значение.
Особенности использования фактов-переменных
В примере выше использовался факт-переменная город_V, особенностью которого является то, что такой факт всегда один и он сам несет значение терма, объявленного в декларации.
class facts город_V:string Город.
Здесь факт город_V имеет строковое значение. Возможны значения любых объявленных доменов, например
domains мойДомен=персона(string Имя,unsigned Возраст). class facts персона_V:мойДомен.
В отличие от обычных фактов, факт-переменная всегда существует и должен иметь начальное значение. Начальное значение факту-переменной можно задать при объявлении
domains мойДомен=персона(string Имя,unsigned Возраст). class facts персона_V:мойДомен:=персона("Старик",80). город_V:string:="НеИзвестен".
В динамических классах начальное значение вместо декларации можно задать в клаузе конструктора
implement dynamicClass domains мойДомен=персона(string Имя,unsigned Возраст). class facts персона_V:мойДомен. clauses new():- персона_V:=персона("Старик",80), ... end implement dynamicClass
Бывает, что конкретное начальное значение установить невозможно по смыслу реализации. Тогда начальное значение может быть установлено как "неустановленное".
class facts город_V:string:=erroneous.
где erroneous - ключевое слово языка. Факт со значением erroneous не может быть использован (точнее: при попытке его использования будет выдана соответствующая ошибка), можно только проверить является ли значение факта неустановленным с помощью детерминированного предиката isErroneous(...)
implement dynamicClass domains мойДомен=персона(string Имя,unsigned Возраст). class facts город_V:string:=erroneous. персона_V:мойДомен. clauses new():- персона_V:=персона("Старик",80), ... clauses ... isErroneous(город_V), ... end implement dynamicClass
С учетом сказанного наш пример
class facts город_V:string Город.
на этапе компиляции выдаст ошибку, поскольку статический факт не инициализирован при объявлении.
Константы и домены
Константы и домены могут объявляться везде - в декларациях классов, интерфейсов и в имплементациях. По своей сущности они, естественно, имеют статический характер. Объявления, сделанные в имплементации, видимы только внутри этой же имплементации. Объявления констант и доменов, сделанные в декларации класса или интерфейса, являются глобальными. Конкретное использование осуществляется путем добавления префикса декларации соответствующего класса или интерфейса в формате
<имя декларации класса или интерфейса>::<имя домена или константы>.
Взаимоотношени статических и динамических сущностей
Клаузы предикатов, объявленных статическими, не могут обращаться к динамическим сущностям (предикатам и фактам). То есть нельзя так:
implement dynamicClass clauses staticPred():- ... dynamicPred(), ... end implement dynamicClass
Клаузы предикатов, объявленных динамическими, такого ограничения не имеют. Как статические так и динамические факты могут хранить указатели на динамические предикаты и экземпляры классов.