Классы. Наследование: различия между версиями

Материал из wikiru.visual-prolog.com

Строка 1: Строка 1:
=Не редактировать. Статья в работе=
Обсуждаемы далее механизмы наследования включают понятие "правила видимости".
В VIP:
В вульгарной интерпретации под правилом видимости мы понимаем возможность обращения к константам, доменам, предикатам, клаузам и фактам (базовым элементам языка) одной сущности из какой-либо другой сущности. Такими сущностями являются классы и объекты.
1. Правила видимости существуют, но нет ни одного ключевого слова для их обозначения, то есть и ключевое слово protected тоже исчезло. В VIP все правила видимости определяются местом декларации сущности.  


2. Понятие АBSTACT CLASS не используется, его заменила более гибкая конструкция Interface
В VIP все правила видимости определяются местом декларации. Таким местом может быть:
*декларация класса (class ... end class)
*декларация интерфейса (interface ... end interface)
*имплементация класса (implement ... end implement)


3. Ключевое слово STATIC не используется, его аналогом являются конструкции class predicates и class facts.
Рассмотрим следующие программные конструкции
 
<vip>
4. Имя интерфейса является также и именем домена, что дает возможность взаимных преобразований интерфейсов по общим правилам преобразования доменов (семантически допустимым, естественно).
 
Сразу подчеркну, что факты подчиняются только правилу видимости private. Это сделано намеренно.
 
а вот пример действия правила protected
 
 
Код
class parent:parent
class parent:parent
end class
end class
Строка 21: Строка 15:
predicates
predicates
  helloWorldFromParent:(string Text).
  helloWorldFromParent:(string Text).
end interface parent
end interface parent


Строка 28: Строка 21:
   helloWorldFromParent(Text):-
   helloWorldFromParent(Text):-
     write(Text).
     write(Text).
end implement parent
end implement parent


class child:child
class child:child
Строка 37: Строка 28:
interface child
interface child
  helloWorldFromChild:(string Text).
  helloWorldFromChild:(string Text).
end interface child
end interface child


implement child
implement child
  inherits parent
  inherits parent
  clauses
  clauses
     helloWorldFromChild(Text):-
     helloWorldFromChild(Text):-
       write(Text).
       write(Text).
end implement child
end implement child
 
</vip>
 


Здесь  
Здесь  
helloWorldFromChild(...) - подчиняется правилу public  
helloWorldFromChild(...) - подчиняется правилу public  
а на  
а на  
Строка 62: Строка 47:
helloWorldFromChild(...), так и к предикату helloWorldFromParent(...).  
helloWorldFromChild(...), так и к предикату helloWorldFromParent(...).  


Цитата
А что вы имели ввиду под словосочетанием "более гибкая". Вы имели ввиду это? :
Цитата
Имя интерфейса является также и именем домена
Имя интерфейса является также и именем домена
Да, операции преобразования интерфейсов являются одной из составляющих гибкости.


объединение предикатов нескольких интерфейсов или подмена одного интерфейса другим легко делается с помощью объявления supports, например,  
объединение предикатов нескольких интерфейсов или подмена одного интерфейса другим легко делается с помощью объявления supports, например,  


 
<vip>
Код
interface myInterface
interface myInterface
  supports myInterface1
  supports myInterface1
  supports myInterface2
  supports myInterface2
end interface myInterface
end interface myInterface
 
</vip>


Если у Вас есть интерфейсы myInterface1 и myInterface2, то через myInterface можно оперировать предикатами из myInterface1 и myInterface2 как предикатами одного интерфейса. В добавок myInterface тоже может иметь свой список объявлений предикатов.  
Если у Вас есть интерфейсы myInterface1 и myInterface2, то через myInterface можно оперировать предикатами из myInterface1 и myInterface2 как предикатами одного интерфейса. В добавок myInterface тоже может иметь свой список объявлений предикатов.  
Строка 99: Строка 75:
2. Причина дисциплинарного характера - выполнять операции над фактами только через соответствующие предикаты. Глобальные данные должны храниться в объекте, о котором должны знать те, кому положено.  
2. Причина дисциплинарного характера - выполнять операции над фактами только через соответствующие предикаты. Глобальные данные должны храниться в объекте, о котором должны знать те, кому положено.  


Учитывая 2, не стали бороться с 1.
Цитата
В обьявлении класса указываются ТОЛЬКО интерфейс (притом один)
да, один. Если интерфейс не указывается, то класс является статическим, то есть не способен порождать объекты.
Цитата
а вот наследование методов происходит только в имплементах. Или я не угадал?
Может и угадали, если понимаете глубже.
В имплементации происходит наследование классов (точнее - объектов-экземпляров этих классов), а вот наследуются методы или нет - это определяется интерфейсами, которые эти классы поддерживают. Кроме того, предикаты, объявленные внутри имплементации видны только изнутри только этой имплементации.  
В имплементации происходит наследование классов (точнее - объектов-экземпляров этих классов), а вот наследуются методы или нет - это определяется интерфейсами, которые эти классы поддерживают. Кроме того, предикаты, объявленные внутри имплементации видны только изнутри только этой имплементации.  


Ниже я переименовал классы и интерфейсы, чтобы было яснее где что.  
Ниже я переименовал классы и интерфейсы, чтобы было яснее где что.  
 
<vip>
 
Код
class parentClass:parentInterface
class parentClass:parentInterface
end class parentClass
end class parentClass
Строка 146: Строка 107:
interface childInterface
interface childInterface
end interface childInterface
end interface childInterface
 
</vip>


publicPredicate() доступен из класса childClass,а  
publicPredicate() доступен из класса childClass,а  
Строка 152: Строка 113:
кроме как в самом классе parentClass.  
кроме как в самом классе parentClass.  


 
*Интерфейс никак не зависит от класса - это именованный набор предикатов и/или доменов и/или констант.  
Цитата
*Класс поддерживает некоторый интерфейс (своей имплементацией), если этот интерйес указан в декларации класса.  
Коль, обьявления класса основывается на интерфейсах и описывается в декларативной части, а реализация наследуется и описывается в имплементной, то можно предположить, что можно, в принципе, заинтерфейснить от одного, а заинхеритить от другого, никак (даже далеко) не связанного с данным интерфейсом класса, лиш бы в итоге все методы с полями интерфейса были реализованны. Или не так?
*Имплементация всегда соответствует классу и имеет с ним одно имя.  
 
*Если класс поддерживает интерфейс, то имплементация должна тем или иным образом привести к клаузу для каждого предиката интерфейса.  
Выражение "...'заинтерфейсить' от одного, а 'заинхеритить' от другого..." - без указания сущности использует не рядоположенные понятия, в первом случае - интерфейс, во втором-класс.
 
Лучше смотреть с такой позиции:
a) Интерфейс никак не зависит от класса - это именованный набор предикатов и/или доменов и/или констант.  
 
B) Класс поддерживает некоторый интерфейс (своей имплементацией), если этот интерйес указан в декларации класса.  
 
c) Имплементация всегда соответствует классу и имеет с ним одно имя.  
 
d) Если класс поддерживает интерфейс, то имплементация должна тем или иным образом привести к клаузу для каждого предиката интерфейса.  


Поэтому может быть много разных классов , поддерживающих один и тот же интерфейс.  
Поэтому может быть много разных классов , поддерживающих один и тот же интерфейс.  
Цитата
Цитата
Если интерфейс не указывается, то класс является статическим, то есть не способен порождать объекты.
А есть особенности его наследования? (статические методы остаются статическими)


Статический класс не наследуется - у него нет ни конструктора, ни интерфейса, а они необходимы для работы механизма наследования.  
Статический класс не наследуется - у него нет ни конструктора, ни интерфейса, а они необходимы для работы механизма наследования.  
Цитата
В 5-ке в классе описывается весь интерфейс, а в 6-ке есть интерфейсы, и что теперь описывается в классе (class : interface >...< end class)?
Т.е. класс потдерживает некий интерфейс (набор фактов и предикатов) прлюс ещё некий набор статических фактов и предикатов?




Да, класс может поддерживать некий интерфейс и плюс набор статических сущностей.  
Да, класс может поддерживать некий интерфейс и плюс набор статических сущностей.  


Цитата
Цитата
В имплементации происходит наследование классов,  
В имплементации происходит наследование классов,  
а вот наследуются методы или нет - это определяется интерфейсами, которые эти классы поддерживают.
а вот наследуются методы или нет - это определяется интерфейсами, которые эти классы поддерживают.
Опа. Это тема, видимо, касается и predicates from.
А можно показать пример для уточнения, как интерфейсы влияют на наследование.
А то я, по ранее написанному, понял, что пока явно не пропишешь predicates from,
то все наследуемые предикаты protected, независимо от совпадения имён и интерфейс
наследуемого предиката ваще игнорируется.
Нет, конструкция "predicates from ..." - это из разряда охотничьих рассказов "... А вот у меня однажды случай был...!... И тогда я ..."
Здесь все проще.


Из иплементации дочернего класса видны все предикаты, декларированные в интерфейсах родительских классов.  
Из иплементации дочернего класса видны все предикаты, декларированные в интерфейсах родительских классов.  
Строка 210: Строка 134:


Допустим, есть классы - родители (я опускаю синтаксические детали вроде end class... и похожие)  
Допустим, есть классы - родители (я опускаю синтаксические детали вроде end class... и похожие)  
 
<vip>
parentClass_1:Interface_1  
parentClass_1:Interface_1  
parentClass_2:Interface_2  
parentClass_2:Interface_2  
</vip>
Имплементации классов parentClass_1 и parentClass_2 поддерживают предикаты, декларированные в интерфейсах Interface1 и Interface2, соответственно.  
Имплементации классов parentClass_1 и parentClass_2 поддерживают предикаты, декларированные в интерфейсах Interface1 и Interface2, соответственно.  


Допустим, есть дочерний класс childClass:childInterface  
Допустим, есть дочерний класс childClass:childInterface  
Пусть есть интерфейс  
Пусть есть интерфейс  
<vip>
interface childInterface  
interface childInterface  
supports Interface_1  
supports Interface_1  
</vip>
Примечание: для такого случая можно было бы иметь  
Примечание: для такого случая можно было бы иметь  
декларацию класса в виде childClass:Interface_1  
декларацию класса в виде childClass:Interface_1  


Теперь пусть есть имплементация дочернего класса:  
Теперь пусть есть имплементация дочернего класса:  
 
<vip>
 
Код
implement childClass
implement childClass
  inherits parentClass_1
  inherits parentClass_1
  inherits parentClass_2
  inherits parentClass_2
 
</vip>
 
Что и откуда можно видеть?  
Что и откуда можно видеть?  
1. из имплемнтации childClass видны (могут быть вызваны):  
1. из имплемнтации childClass видны (могут быть вызваны):  
Строка 236: Строка 160:
B) все предикаты, декларированные интерфейсе Interface_1  
B) все предикаты, декларированные интерфейсе Interface_1  
с) все предикаты, декларированные интерфейсе Interface_2  
с) все предикаты, декларированные интерфейсе Interface_2  
2. Из какого-либо класса вне childClass видны (могут быть вызваны) при обращеии к его экземпляру:  
2. Из какого-либо класса вне childClass видны (могут быть вызваны) при обращеии к его экземпляру:  
a) все предикаты, непосредственно декларированные интерфейсе childInterface  
a) все предикаты, непосредственно декларированные интерфейсе childInterface  

Версия 14:03, 26 сентября 2007

Обсуждаемы далее механизмы наследования включают понятие "правила видимости". В вульгарной интерпретации под правилом видимости мы понимаем возможность обращения к константам, доменам, предикатам, клаузам и фактам (базовым элементам языка) одной сущности из какой-либо другой сущности. Такими сущностями являются классы и объекты.

В 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

Здесь 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