Эта заметка описывает способы вызова метода базового класса на языке Cache ObjectScript.Cache предлагает два способа вызова базового класса, причем эти способы являются зависимыми от версии сервера. Первый способ состоит в смене контекста трансляции, второй в приведении типа объекта. Смена контекста трансляции работает на младших версиях Cache, версии 3 и ее модификации. Приведение типа объекта работает начиная с версии 3.2.2 (видимо, в билд попадают работы по четверке) и старше. В версиях 4 и старше рекомендуется использовать приведение типа.
Положим, что существует два класса, один из которых наследован от другого и наследник переопределяет одну из функций базового класса. В переопределенной функции требуется вызвать такую же функцию базового класса. Положим, имя базового класса BaseClass, имя наследника DerivedClass. Положим, что переопределяемый метод называется Func.
Смена контекста трансляции выполняется директивами #classcontext / #endclasscontext. В переопределяемом методе следует сменить контекст, в измененном контексте вызвать переопределяемую функцию, вернуть контекст. После чего трансляция продолжается в контексте наследника. Директивы #classcontext / #endclasscontext работают в стековом режиме, #classcontext сохраняет текущий контекст и переключается в указанный, #endclasscontext восстанавливает сохраненный контекст.
Пример вызова метода базового класса в переопределяемом методе с помощью смены контекста трансляции:
method Func()
{
classmethod = 0;
not final;
code =
{
w 123,! ; некий код переопределенного метода DerivedClass.Func()
#classcontext BaseClass
d ..Func() ; вызов BaseClass.Func() для этого же объекта
#endclasscontext BaseClass
w 456,! ; продолжение кода переопределенного метода DerivedClass.Func()
q
}
}
Для вызова метода базового класса путем приведения типа используется конструкция вида ##class(=ClassName)##this.MethodName(Arguments). Здесь участвует даже две директивы препроцессора. Способ рекомендуется начиная с версии Cache 4 и старше, но работает также и в версии 3.2.2. Приведение типа есть практически то же самое по отношению к компилятору классов, что и смена контекста трансляции, то есть есть способ указать, что переменную %this (макродиректива ##this) следует рассматривать как относящуюся к заданному классу. Этот способ технически выполнен более грамотно. Действительно, для целей приведения типа (кастинг) он подходит наилучшим образом.
Пример вызова метода базового класса путем приведения типа:
method Func()
{
classmethod = 0;
not final;
code =
{
w 123,! ; некий код переопределенного метода DerivedClass.Func()
d ##class(=BaseClass)##this.Func() ; вызов BaseClass.Func() для этого же объекта
w 456,! ; продолжение кода переопределенного метода DerivedClass.Func()
q
}
}
Различие способов вызова метода базового класса в разных версиях Cache ставит проблему написания кода, переносимого от версии к версии. В этих целях можно использовать либо административный подход, либо программный. В административном подходе просто запрещается использование какой-либо версии, и явно указывается, что писать следует под вполне определенную, например под четвертую. В программном подходе следует использовать конструкции, которые автоматически должны определить версию сервера и использовать соответствующий метод.
Автоматически определить версию сервера можно, используя либо директивы препроцессора, либо выполнив переопределяемые методы в виде генераторов.
Использование директив препроцессора. Используем директивы исполнения при трансляции, например директиву #if:
method Func()
{
classmethod = 0;
not final;
code =
{
w 123,! ; некий код переопределенного метода DerivedClass.Func()
#if $p($$GetVersion^%apiOBJ()," ",4)<4
#classcontext BaseClass
d ..Func() ; вызов BaseClass.Func() для этого же объекта
#endclasscontext BaseClass
#else
d ##class(=BaseClass)##this.Func() ; вызов BaseClass.Func() для этого же объекта
#endif
w 456,! ; продолжение кода переопределенного метода DerivedClass.Func()
q
}
}
Этот способ я не проверял, и привожу его только теоретически. Второй способ является более надежным, поскольку использует технику, являющуюся общей для всех версий Cache.
Использование методов - генераторов. В генераторе просто вставляем определение версии Cache и в зависимости от нее генерируем различный код:
generator =
{
s %code=0
$$$GENERATE(" w 123,!") ; некий код переопределенного метода DerivedClass.Func()
if $p($$GetVersion^%apiOBJ()," ",4)<4 d ; определяем версию
. $$$GENERATE(" #classcontext BaseClass")
. $$$GENERATE(" d ..Func()") ; первый способ
. $$$GENERATE(" #endclasscontext BaseClass")
e $$$GENERATE(" d ##class(=BaseClass)##this.Func()") ; второй способ
$$GENERATE(" w 456,!") ; продолжение кода переопределенного метода DerivedClass.Func()
$$$GENERATE(" q")
q $$$OK
}
Комментариев нет:
Отправить комментарий