powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Имя класса в расчетном свойстве при наследовании
25 сообщений из 37, страница 1 из 2
Имя класса в расчетном свойстве при наследовании
    #36476930
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я правильно понимаю, что при наследовании в расчетном свойстве имя класса можно узнать только так:
Код: plaintext
s className=$p({x__classname},"~",$l({x__classname},"~")- 1 )
?
что-то использование %%CLASSNAME не помогает - в нем всегда имя суперкласса...

Неужто нет более простого пути?

Замысел в том, чтобы в предке определить свойство так:
Код: plaintext
1.
2.
3.
Property IsAny As %Boolean [ Calculated, SqlComputeCode = {
		s className=$p({x__classname},"~",$l({x__classname},"~")- 1 )
		s {IsAny}=$zobjclassmethod(className,"GetIsAny",{ID})
	}, SqlComputed ];
И расчет свойства описать и в предке, и в потомках. Тогда SQL и объектный доступы должны давать идентичный результат.

И еще тогда вопрос. Как "правильнее" обозвать метод - "GetIsAny" или "IsAnyGet"? Какие-то же должны быть соображения в пользу одного или другого варианта (вроде бы второй как бы конфликтует с темой геттера, но компилится без ошибок и работает, на первый взгляд, нормально).
Тем более, что Каше не даст в наследнике определить это свойство, как не расчетное (хранимое, например).
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36477682
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По-прежнему прячете методы в параметр свойства...
Но виноват и могу предложить такой способ:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
///<var>bclass</var> - {%%CLASSNAME}, базовый класс
///<var>xclass</var> - {x__classname}, классы расширения
ClassMethod GetClassName(bclass as %String="", xclass as %String="") as %String [SqlProc]{
 Q:xclass="" bclass
 s dm="~", len=$l(xclass,dm) 
 Q $P(xclass,dm,len- 1 ) ; !!! всего-лишь имя последнего класса
}
На самом деле не все так просто. Такая реализация метода не универсальна и будет неправильно работать при наследовании из разных пакетов, использования имени пакета по умолчанию и т.д.
Короче нуждается в доработке
К тому же я столкнулся с ошибкой при получении {%%CLASSNAME}. В некоторых случаях, что-то происходит, и SQL так и возвращает "%CLASSNAME".
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478032
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint,

%%CLASSNAME подставляется в момент компиляции и у всех унаследованных классов будет один вроде как.... если только не переписать метод для потомков, НО

1. select капитан from баржа
и
2. select капитан from плавсредство

в случае, если "капитан" - расчитывается

например, для баржи на основании информации об отпусках - "Вася в отпуске, значит капитан - Петя"

а для плавсредства там пустышка лежит ("У плавсредства не всегда есть капитан, например, у баржи есть, а у плотика - нету, потому рассчитывать конкретных капитанов поручено потомкам, среди которых и "баржа")

Так вот - 2-й запрос вернет пусто для всех записей - в т.ч. и для барж.
Задачка в том, чтобы при расчете свойства капитан в "плавсредстве" вызвать не пустой его метод, а выяснить для начала, что наше плавсредство - конкретно "баржа" и использовать метод расчета оттуда.

Понятно, что есть соответствующий паттерн. Но Каше его не выполняет физически - он при работе через объект отработает верно, а при работе через скл "забудет" о наследовании... Всего-то дел, обойти ситуацию...

Не увидел отличий в наших предложениях... Да, "всего лишь имя последнего класса"... т.е. класса, к которому реально относится мой экземпляр и метод которого нужно заставить вызвать нерадивого предка, который норовит вызвать свой метод...
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478140
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну так и обойдите, зачем так упираться в рассчитываемые свойства.
В родителе
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 ///для переопределения в наследниках
 ClassMethod GetCaptainName(ID as %String) as %String [Private] {
   q "" ;заглушка
 }
 ///Общий интерфейс для всех наследников 
 СlassMethod GCN(ID as %String) as %String[SqlProc] {
  q ..GetCaptainName(ID)
 } 

В потомках
Код: plaintext
1.
2.
3.
4.
5.
 ///Переопределяем если надо
 ClassMethod GetCapitainName(ID as %String) as %String [Private] {
  ;например  
  q ..captainNameGetStorage(id) ; или что-нить еще
 }
В коде
Код: plaintext
1.
 s sql="Select ID,ParentClass_GCN(ID) From ChildrenClass"
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478160
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"всего-лишь имя последнего класса" - это я к тому, что могут быть проблемы с именами пакетов
kolesov Не увидел отличий в наших предложениях
Хм, определение имени класса не относится к функции класса предметной области и должно быть вынесено в отдельный класс (программу) и т.д. Но это я опять, о своем... :)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478223
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint,

Но ведь с классами-то как раз нет проблем - там все при наследовании схватывается хорошо.
Определение имени класса действительно будет не здесь... Оно будет (и уже есть ;) на самом верху наследования - у того класса, от которого я наследую все хранимые классы своей системы...
Реальный код выглядит так:

Код: plaintext
1.
2.
Property IsConfirmNeeded As %Boolean [ Calculated, SqlComputeCode = {
		s {IsConfirmNeeded}=$zobjclassmethod({SqlClassName},"IsConfirmNeededGet",{ID})
	}, SqlComputed ];
Где SqlClassName теперь расчитывается для всех классов... И тут он мало чем отличается от
Код: plaintext
1.
2.
Property IsConfirmNeeded As %Boolean [ Calculated, SqlComputeCode = {
		s {IsConfirmNeeded}=##class({%%CLASSNAME}).IsConfirmNeededGet({ID})
	}, SqlComputed ];
Вопрос-то в другом - почему-то нет дефолтового способа вытащить имя класса конкретного экземпляра в контексте именно скл... М.б. это неспроста? Бывает, что нечто не придумано до тебя потому, что это нечто и не стоит придумывать ;)

А излишнее поклонение идолу, с названием "Домэин Моудел", кстати, часто превращает код в совершенно нечитаемый набор "постоянных вызовов неизвестно чего неизвестно откуда" ;) Я склонен с сомнением относиться к фразе про то, что в методе должно быть 5-10 строк... Нужно взвешивать еще и читабельность кода... пусть она даже будет и в ущерб принципам распределения обязанностей в модели предметной области...
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478269
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот... бяка была вот в чем:

<METHOD DOES NOT EXIST>%0AmBr7^CacheSql9 *IsConfirmNeededGet

Эта ошибка произошла в связи с тем, что у потомка не был переопределен наш метод расчета свойства....

Т.е. если зайти с той стороны, откуда попытался зайти я, снова упираемся в то, что скл слабо разбирается в наследовании...

Итого получается, что даже если метод расчета есть в предке, в потомке я его должен все равно написать, чтобы иметь к расчетному свойству нормальный доступ через скл.

Или использовать хранимку... но это мне не очень симпатично - громоздко выглядит ее вызов в коде ;(

Или идти по старому пути - в родительском методе обсчитывать свойство исходя из того, какого класса объект выбран... это-то точно работает ;)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478299
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovчто в методе должно быть 5-10 строк не более чем рекомендация.
[quote kolesov]обсчитывать свойство исходя из того, какого класса объект выбран... это-то точно работает[quote] но как "идеологически" неправильно :), наследование как раз для этого. Лучше хранимку
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478326
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще с расчетными свойствами что-то не так, суть есть оболочка над методами класса (что с точки зрения SQL = хранимая процедура). Имхо, надо использовать только в самых простых случаях
Код: plaintext
 s {A}={B}+{C} 
И то лишь из за компактности. И тоже, имхо, но зачем Вы их так активно используете?
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478367
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovОно будет (и уже есть ;) на самом верху наследования
Хм, как-то сомневаюсь я. У меня вообще в программе $$getName^class(bclass,xclass). На крайний случай в класс с утилитами.
kolesovА излишнее поклонение идолу, с названием "Домэин Моудел" ... "постоянных вызовов неизвестно чего неизвестно откуда"
"Шо занадта, то не здрово". Излишнее поклонение чему угодно, приводит к печальным последствиям.
Код: plaintext
 s cn=##class(ClassUtilites).GetClassName(bclass,xclass)

Проблемы? :)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478403
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefintИ то лишь из за компактности. И тоже, имхо, но зачем Вы их так активно используете?

По многим причинам... навскидку:
- архитектура системы становится легкой и понятной;
- каше позволяет (2 млн. таких свойств расчитывается за 30 сек, а если в выборке есть ограничения, например по интервалу дат, где есть индексы, то расчет - меньше секунды)
- ZEN располагает к их использованию (вместо сложностей с colExpression в таблице могу просто указать colName и не заботиться о том, как по таким полям сортировать и фильтровать)
- совместно с "->", и наследованием, на мой взгляд, является основным преимуществом перед обычным скл, где я писал и вызывал хранимки (ведь и сейчас можно по-честному джойнить таблицы... Вы это делаете? я - нет...)
- если в хранимую процедуру передается только ID - она первый кандидат в вычисляемое свойство, потому что хранимки в каше, имхо, нужны для более сложных вещей (вычислить значение на дату или для конкретного юзера...)
- это работает. 2 года. и не было пока ни одного случая, чтобы при падении производительности ее нельзя было вырастить в 100 или 100 000 (и такое бывало ;) раз.
- ...
МастХэв, в опчем ;)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478422
Turk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kolesovЯ правильно понимаю, что при наследовании в расчетном свойстве имя класса можно узнать только так:
Код: plaintext
s className=$p({x__classname},"~",$l({x__classname},"~")- 1 )
?
что-то использование %%CLASSNAME не помогает - в нем всегда имя суперкласса...

Неужто нет более простого пути?

Свойство {x__classname} не всегда бывает определено, т.е. вышеприведенный код может вернуть пустую строку (с последующей ошибкой "класс не существует" в $zobjclassmethod()).
Есть метод %ClassName(), который возвращает имя класса открытого объекта:
Код: plaintext
1.
2.
3.
set obj=##class({%%CLASSNAME}).%OpenId({%%ID})
set className=obj.%ClassName( 1 )
kill obj
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478444
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как вариант:
Код: plaintext
1.
2.
3.
4.
Property IsAny As %Boolean [ Calculated, SqlComputeCode = {
		s className=##class({%%CLASSNAME}).%OpenId({ID}).%ClassName( 1 )
		s {*}=$zobjclassmethod(className,"GetIsAny",{ID})
	}, SqlComputed ];
Но я его Вам не рекомендую.

Если знаете английский, то здесь есть более правильное решение Вашей проблемы.
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478446
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint
Код: plaintext
1.
 s sql="Select ID,ParentClass_GCN(ID) From ChildrenClass"


Ну вот опять!?

Это НЕ РАБОТАЕТ!!! Вернее работает, но неправильно... зато очень прикольно характеризует движок, я рыдал:

Код: plaintext
1.
2.
select superClass_IsConfirmNeededProc(ID) from superClass
select subClass01_IsConfirmNeededProc(ID) from subClass01
select superClass_IsConfirmNeededProc(ID) from subClass01
и апофеоз:
Код: plaintext
select subClass01_IsConfirmNeededProc(ID) from subClass02

Результат приводить не буду... но поверьте, он печальный...
Вывод - хранимки и каше еще менее совместимы, чем расчетные поля и каше ;(
Во всяком случае, при наследовании...
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478457
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TurkСвойство {x__classname} не всегда бывает определено
Опаньки, а КОГДА оно бывает неопределено? Я думаю, я бы об этом знал... пользователи позвонили бы ;)
TurkЕсть метод %ClassName(), который возвращает имя класса открытого объекта:
Код: plaintext
1.
2.
3.
set obj=##class({%%CLASSNAME}).%OpenId({%%ID})
set className=obj.%ClassName( 1 )
kill obj

У меня одна сотрудница, по неопытности, и давно, что-то подобное сделала... Хорошо, вовремя заметили.... На миллионах записей такой код положит сервер...
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478481
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovПо многим причинам... навскидку: Итого - Zen, все остальное прекрасно существует без Calculated свойств. Которые как мы помним kolesovТам с этими расчетными свойствами вообще-то песня и неприятностей много (не программу пишешь, а по болоту по кочкам прыгаешь) :)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478492
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefint,

Я и ко всему Каше примерно так отношусь... что с того... Он куплен, и никуда я с подводной лодки не денусь ;)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478602
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit дал ссылку на надежное решение (блин, можно было бы и самому дойти)
в родительском классе
Код: plaintext
1.
2.
3.
4.
5.
  Property ClassName as %String[InitialExpression={..%ClassName( 1 )},ReadOnly];
  ClassMethod GCN(ID) as %String[SqlProc]{
    q:'..%ExistsId(ID) "Unknown"
    q ..ClassNameGetStored(ID)
  }
 

"Select ID,ParentClass_GCN(ID) From ChildrenClass" - работает'
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478610
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesov
и не было пока ни одного случая, чтобы при падении производительности ее нельзя было вырастить в 100 или 100 000 (и такое бывало ;) раз.

Можно я ссылку на это в разделе "Сравнения СУБД" запощу :)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36478625
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesovTurkСвойство {x__classname} не всегда бывает определено
Опаньки, а КОГДА оно бывает неопределено? Я думаю, я бы об этом знал... пользователи позвонили бы ;)
Цитата :
Код: plaintext
For the root class of an extent, this value is always empty.

Для проверки выполните в области SAMPLES:
Код: plaintext
select x__classname from Cinema.Film
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36479026
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
doublefintProperty ClassName as %String[InitialExpression={..%ClassName(1)},ReadOnly];

Да, я как раз вчера об этом и думал вечером - как мне это свойство установить у примерно 3 млн. объектов в работающей системе. Нет соображений?

С учетом того, что у меня нет уверенности, что часть объектов БД даст себя сохранить (при наступлении определенных условий изменения некоторых объектов запрещены ;)
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36479038
Socratdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kolesov,

Когда-то давно столкнулись с такой проблемой и сразу же завели такое свойство в родителе:
Код: plaintext
1.
Property class As %String(MAXLEN =  2000 ) [ Final, InitialExpression = {$S($G(%this):$zobjclass(%this), 1 :"")}, ReadOnly ];

Заапдейтить поле не проблема ручками через SQL, если таблиц немного..
Код: plaintext
&sql(UPDATE Sample.Person SET class = 'Sample.Person')

Только не забудьте снять ReadOnly со свойства перед этим...

Вычисляем свойства так:
Код: plaintext
1.
Property name As %String [ Calculated, SqlComputeCode = {s {*}=$zobjclassmethod({class},"getName",{%%ID})}, SqlComputed ];
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36479143
Turk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
kolesovTurkСвойство {x__classname} не всегда бывает определено
Опаньки, а КОГДА оно бывает неопределено? Я думаю, я бы об этом знал... пользователи позвонили бы ;)
Например, так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
    <Data name="TestClassDefaultCN">
        <Attribute>%%CLASSNAME</Attribute>
        <Structure>node</Structure>
        <Subscript> 0 </Subscript>
    </Data>
    <Data name="TestClassDefaultData">
        <Value name="1">
            <Value>поле1</Value>
        </Value>
        ...
        <Value name="N">
            <Value>полеN</Value>
        </Value>
    </Data>
    <DefaultData>TestClassDefaultData</DefaultData>

kolesov
TurkЕсть метод %ClassName(), который возвращает имя класса открытого объекта:
Код: plaintext
1.
2.
3.
set obj=##class({%%CLASSNAME}).%OpenId({%%ID})
set className=obj.%ClassName( 1 )
kill obj

У меня одна сотрудница, по неопытности, и давно, что-то подобное сделала... Хорошо, вовремя заметили.... На миллионах записей такой код положит сервер...
Если не закрывать открытый объект ( kill, не %Close()! ), то да - рано или поздно Cache "встанет".
Можно также передать открытый объект в вызываемый метод вместо ID (если конечно ID внутри медота используется для открытия объекта) и лишь после этого закрывать этот объект.
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36479158
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolesov,
Если сложная логика, вернитесь (осторожно!!! - не забываем про пакеты и пустые значения) к использованию служебного свойства x__classname, у меня работает
...
Рейтинг: 0 / 0
Имя класса в расчетном свойстве при наследовании
    #36481834
Фотография kolesov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подытоживая, могу сказать одно. Попытка действовать вне правила "решение должно быть тупое... если можно сделать решение еще тупее, то немедленно так и делаем", приводит к неприятностям, во всяком случае, с Каше.

Хорошо, что там, где мне нужно, x__classname всегда работает (отдельно хранить то, что и так хранится, м.б. и стоит, но я так все-же делать не стану ;)

Вызвать при расчете свойства метод реального потомка не получится (так устроена скл-проекция, как я понял). При попытке такого вызова система (по непонятным причинам) не обратит внимания на то, был ли унаследован искомый метод, и, если в наследнике он отдельно не определен, обломит с ошибкой "метод не найден".

Заниматься проставлением во всех наследниках заглушек на все методы предков - махровый ононизм, как мне кажется...

Итого - проблема неразрешима в рамках текущей модели скл-доступа. И использовать я все же буду самое первоначальное и неубиваемое решение: расчетом свойств всех потомков будет заниматься их предок. Это тупо, дебильно, зато работает.... За то время, что я пытался (в очередной раз) придумать нечто красивое на Каше, мог бы написать гору тупого кода, и сейчас бы пиво пил, а не работал ;)
...
Рейтинг: 0 / 0
25 сообщений из 37, страница 1 из 2
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Имя класса в расчетном свойстве при наследовании
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]