Миксины и трейты#
В разделе описаны механизмы наследования классов сущностей с помощью миксинов и трейтов, их создание, подключение, кодогенерация и особенности использования.
Механизмы наследования#
Фреймворк не поддерживает полноценное классическое наследование классов сущностей. Понятие «наследование» используется для описания логической связи двух классов.
Вместо классического наследования фреймворк использует миксины и трейты.
Миксин (Mixin)#
Миксин (англ. mix-in) — это элемент языка программирования, обычно класс или модуль, реализующий чётко выделенное поведение. Миксин используется для уточнения поведения других классов и не предназначен для самостоятельного создания объектов.
В системе Global3 Postgres миксин — это специализированный класс, каждый объект (запись в таблице) которого соответствует одному объекту подключённого класса (записи в основной таблице). Миксин-класс может быть подключён к неограниченному числу других классов.
Для объектов миксина первичным ключом является поле gidRef. Его значение автоматически устанавливается равным значению поля gid объекта подключённого класса в момент создания.
В API миксина реализуются общие методы, доступные для всех подключённых классов.
Миксин может содержать произвольное число атрибутов. Если имя атрибута миксина совпадает с именем атрибута подключённого класса или его наследника, значение синхронизируется автоматически.
Примечание
Все Scala-классы, соответствующие миксину, наследуются от системных классов D-ветви и имеют префикс D.
Остальные Scala-классы, соответствующие обычным сущностям, наследуются от системных классов S-ветви и имеют префикс S.
Для миксинов метод получения Rop по gidRef называется loadByGid. Также реализован метод, аналогичный методу get для SApi:
getByGid(gidpRef: NGid): Option[ApiRop]
Системные миксины#
Системные миксины функционально не отличаются от прикладных. Основной системный миксин — Btk_Object.
При формировании кода для классов с supertype="document" и supertype="reference" этот миксин автоматически подключается к классу.
Миксин обеспечивает базовую инфраструктурную функциональность: корректную работу версионирования, аудита изменений и синхронизации данных.
Миксин Btk_Object можно отключить с помощью свойства в ODM-файле:
<reflection isEnabled="false"/>
Пример см. в классе Btk_Group.
Прикладные миксины#
Все остальные миксины, например bs_settler, создаются разработчиками вручную для решения конкретных прикладных задач и не являются частью системной функциональности.
Создание класса-миксина#
В ODM-файле необходимо объявить атрибут gidRef:
<attr name="gidRef" attribute-type="Varchar"/>
Для класса необходимо указать свойство supertype="mixin":
<class xmlns="http://www.global-system.ru/xsd/global3-class-1.0"
name="Xxx_ClassName" supertype="mixin"/>
Формирование кода#
При формировании кода для класса-миксина Dpi наследуется от MixinApi:
trait Xxx_XxxxDpi[T] extends MixinApi[java.lang.Long, ARO, API]
Dvi наследуется от AppMixinAvi:
trait Xxx_XxxDvi extends AppMixinAvi
Основные методы для работы:
//создание по rop мастера, возвращает rop миксина
Api().insertByParent(ropMaster)
//загрузка миксина по gidRef, возвращает rop миксина
Api().loadByGid(gidRef)
//удаления по gidRef
Api().deleteByKey(gidRef)
Объявление подключённых классов#
Для связывания класса с миксином необходимо в ODM-файле указать имена классов-миксинов:
<mixins>
<mixin name="Bs_Settler" isDpiManaged="true"/>
</mixins>
При формировании кода сущности в Dpi добавляется код:
вставки объекта миксина в методе
insert;удаления объекта миксина в методе
delete;установки значений атрибутов миксина. Код добавляется в сеттеры атрибутов сущности, имена которых совпадают с именами атрибутов миксина.
Для ручного управления генерацией миксина необходимо отключить формирование кода в Dpi с помощью настройки isDpiManaged.
По умолчанию для всех подключённых миксинов генерируется код в Dpi.
Ссылочность на миксин#
Для атрибутов, ссылающихся на миксин, необходимо указывать тип refAnyObject:
<attr name="gidSettler"
attribute-type="Varchar"
caption="Контрагент"
type="refAnyObject"
isVisible="false"
order="20"
ref.class="Bs_Settler"/>
Для автоматической генерации атрибутов HL (Head Line) и MC (Mnemo Code), сеттеров этих атрибутов и добавления их в selectStatement и onRefreshExt необходимо указать в настройке ref.class класс миксина для ссылки.
Важно
Для миксинов по ссылочным атрибутам не генерируются внешние ключи. Вместо них генерируются индексы.
Трейт (Trait)#
Трейт — это механизм повторного использования кода между классами. В отличие от наследования класс может содержать несколько трейтов. Трейт не имеет объектов, собственной структуры хранения данных и визуального представления.
Чтобы создать трейт:
Создайте ODM-файл.
Укажите свойство
supertype="trait".
При формировании кода создаются только файлы Dpi и Api. Dpi содержит только объявления сеттеров и геттеров.
Наследование сущности от трейта#
Для наследования сущности от трейта добавьте в ODM свойство класса with="Trait_Name".
Сущность, наследуемая от трейта, должна иметь все атрибуты, объявленные в трейте.
Перекрытие и порядок вызовов методов#
Рассмотрим код трейта и наследуемого от него класса:
trait Gs3_TraitApi[T] extends Gs3_TraitDpi[T] {
override def setFNumber(rop: ApiRop, value: NNumber): Unit = {
Logger.Factory.get(getClass).info("Gs3_TraitApi.setFNumber")
super.setFNumber(rop, value)
}
}
class Gs3_DescendantApi extends Gs3_DescendantDpi[T] with Gs3_TraitApi[T] {
override def setFNumber(rop: ApiRop, value: NNumber): Unit = {
Logger.Factory.get(getClass).info("Gs3_DescendantApi.setFNumber")
super.setFNumber(rop, value)
}
}
В результате выполнения метода Gs3_DescendantApi.setFNumber() последовательность вызовов будет следующей:
Gs3_DescendantApi.setFNumber.Gs3_TraitApi.setFNumber.Gs3_DescendantDpi.setFNumber.