Классы. Наследование
Обсуждаемы далее механизмы наследования включают понятие "правила видимости". В вульгарной интерпретации под правилом видимости мы понимаем возможность обращения к базовым элементам языка (константам, доменам, предикатам, клаузам и фактам) одной сущности из какой-либо другой сущности. Сущностями являются в данном случае классы и объекты.
Примечание. К правилам видимости мы не относим вопросы включения текстов интерфейсов, классов и имплементаций в соответствующие файлы проекта. Такие коллизии включения должны быть разрешены корректно.
В VIP все правила видимости определяются местом декларации. Таким местом может быть:
- декларация класса (class ... end class)
- декларация интерфейса (interface ... end interface)
- имплементация класса (implement ... end implement)
Рассмотрим следующие программные конструкции
class parent:parent end class interface parent predicates helloWorldFromParent:(string Text). end interface parent implement parent clauses helloWorldFromParent(Text):- write(Text). end implement parent class child:child end class interface child helloWorldFromChild:(string Text). end interface child implement child inherits parent clauses helloWorldFromChild(Text):- write(Text). end implement child
Здесь представлены два класса, порождающих объекты: parent (родитель) и child (потомок) helloWorldFromChild(...) - подчиняется правилу public а на helloWorldFromParent(...) - действует правило protected.
У объекта класса child можно вызвать только предикат helloWorldFromChild(...), а из объекта класса child можно обратиться как к предикату helloWorldFromChild(...), так и к предикату helloWorldFromParent(...).
Имя интерфейса является также и именем домена
объединение предикатов нескольких интерфейсов или подмена одного интерфейса другим легко делается с помощью объявления supports, например,
interface myInterface supports myInterface1 supports myInterface2 end interface myInterface
Если у Вас есть интерфейсы myInterface1 и myInterface2, то через myInterface можно оперировать предикатами из myInterface1 и myInterface2 как предикатами одного интерфейса. В добавок myInterface тоже может иметь свой список объявлений предикатов.
Кроме того есть такие возможности, как delegate interface - когда можно передать исполнение предикатов интерфейса объекту, хранящемуся в факте-переменной.
Возможно перекрывать имплементацию предиката(ов) родительского класса имплементацией предиката(ов) дочернего класса, например, родителький класс содержит имплементацию "по умолчанию", а ряд конкретных классов должен реагировать на вызов предикатов особенным образом.
Клаузы для предикаты одного интерфейса могут содержаться в имлементациях разных классов путем использования конструкции predicates from ...
То есть интерфейс есть фасадная часть класса (динамического), а механизмы имплементации могут быть самыми разными.
Я думаю здесь та же история, что и с типизацией в Turbo, PDC и Visual Прологах: технически оправдано и практически ведет к повышению надежности программ.
1. Ни классы, ни интерфейсы не имеют никаких предопределенных предикатов (кроме конструкторов, относящихся только к декларации класса), а видимость фактов предполагает операции над ними и, cоответственно, наличие предопределенных предикатов. 2. Причина дисциплинарного характера - выполнять операции над фактами только через соответствующие предикаты. Глобальные данные должны храниться в объекте, о котором должны знать те, кому положено.
В имплементации происходит наследование классов (точнее - объектов-экземпляров этих классов), а вот наследуются методы или нет - это определяется интерфейсами, которые эти классы поддерживают. Кроме того, предикаты, объявленные внутри имплементации видны только изнутри только этой имплементации.
Ниже я переименовал классы и интерфейсы, чтобы было яснее где что.
class parentClass:parentInterface end class parentClass interface parentInterface predicates publicPredicate:(). end interface parentInterface implement parentClass clauses publicPredicate():- write(""). predicates privatePredicate:(). clauses privatePredicate():- write("TTT"). end implement parentClass class childClass:childInterface end class childClass implement childClass inherits parentClass end implement childClass interface childInterface end interface childInterface
publicPredicate() доступен из класса childClass,а privatePredicate недоступен для использования нигде, кроме как в самом классе parentClass.
- Интерфейс никак не зависит от класса - это именованный набор предикатов и/или доменов и/или констант.
- Класс поддерживает некоторый интерфейс (своей имплементацией), если этот интерйес указан в декларации класса.
- Имплементация всегда соответствует классу и имеет с ним одно имя.
- Если класс поддерживает интерфейс, то имплементация должна тем или иным образом привести к клаузу для каждого предиката интерфейса.
Поэтому может быть много разных классов , поддерживающих один и тот же интерфейс.
Статический класс не наследуется - у него нет ни конструктора, ни интерфейса, а они необходимы для работы механизма наследования.
Да, класс может поддерживать некий интерфейс и плюс набор статических сущностей.
В имплементации происходит наследование классов, а вот наследуются методы или нет - это определяется интерфейсами, которые эти классы поддерживают.
Из иплементации дочернего класса видны все предикаты, декларированные в интерфейсах родительских классов. При обращении же к дочернему классу видны только предикаты, декларированные в интерфейсе этого дочернего класса.
Рассмотрим пример.
Допустим, есть классы - родители (я опускаю синтаксические детали вроде end class... и похожие)
parentClass_1:Interface_1 parentClass_2:Interface_2
Имплементации классов parentClass_1 и parentClass_2 поддерживают предикаты, декларированные в интерфейсах Interface1 и Interface2, соответственно.
Допустим, есть дочерний класс childClass:childInterface Пусть есть интерфейс
interface childInterface supports Interface_1
Примечание: для такого случая можно было бы иметь декларацию класса в виде childClass:Interface_1
Теперь пусть есть имплементация дочернего класса:
implement childClass inherits parentClass_1 inherits parentClass_2
Что и откуда можно видеть? 1. из имплемнтации childClass видны (могут быть вызваны): a) все предикаты, непосредственно декларированные интерфейсе childInterface B) все предикаты, декларированные интерфейсе Interface_1 с) все предикаты, декларированные интерфейсе Interface_2
2. Из какого-либо класса вне childClass видны (могут быть вызваны) при обращеии к его экземпляру: a) все предикаты, непосредственно декларированные интерфейсе childInterface B) все предикаты, декларированные интерфейсе Interface_1