Автор | Сообщение |
|
| |
Пост N: 295
Зарегистрирован: 05.10.06
|
|
Отправлено: 03.03.21 10:11. Заголовок: как реализована объектная модель ?
В конструкции for each var in arr var - содержит значение элемента массива и в то же самое время можно получить дополнительные свойства как объекта var:__enum* Как это реализовано ?
|
|
|
Ответов - 21
, стр:
1
2
All
[только новые]
|
|
|
| Администратор
|
Пост N: 4005
Зарегистрирован: 23.05.05
|
|
Отправлено: 03.03.21 12:08. Заголовок: для этого введен отд..
для этого введен отдельный тип данных: enum. На prg уровне для var нет различия между регулярным типом и enum. Но на уровне C для хранения var а HB_ITEM используется отдельная структура: enum, которая содержит ссылку на элемент массива, и дает доступ к свойствам типа __enumIndex, __enumStart и пр.
|
|
|
|
| |
Пост N: 296
Зарегистрирован: 05.10.06
|
|
Отправлено: 03.03.21 13:04. Заголовок: Pasha пишет: для хр..
Pasha пишет: цитата: | для хранения var а HB_ITEM используется отдельная структура: enum, которая содержит ссылку на элемент массива, и дает доступ к свойствам типа __enumIndex, __enumStart и пр. |
| А можно это как то реализовать в Харбор ? Удобно например из функции вернуть значение,у которого могут быть дополнительные свойства/значения
|
|
|
|
| Администратор
|
Пост N: 4006
Зарегистрирован: 23.05.05
|
|
Отправлено: 03.03.21 14:07. Заголовок: Можно использовать х..
Можно использовать хэш. Это похоже на массив с именованными элементами. Примерно так: FUNC <fn> LOCAL hVal := {=>} hVal[ "Value" ] := <value> hVal[ "Name" ] := <..> ... RETURN hVal отдельно значения у хеш нет, надо использовать его элемент.
|
|
|
|
| постоянный участник
|
Пост N: 1593
Зарегистрирован: 09.10.06
|
|
Отправлено: 03.03.21 14:11. Заголовок: MIKHAIL пишет: В ко..
MIKHAIL пишет: цитата: | В конструкции for each var in arr |
| В папке tests есть пример foreach2.prg Реализация конструкции for each для класса. Может это то, что ищете.
|
|
|
|
| |
Пост N: 297
Зарегистрирован: 05.10.06
|
|
Отправлено: 08.03.21 18:36. Заголовок: Pasha пишет: для эт..
Pasha пишет: цитата: | для этого введен отдельный тип данных: enum |
| А можно сделать на С функцию, которой передавать вид структуры и значения и получать обратно переменную с сылкой на эту структуру и ее элементы ?
|
|
|
|
| Администратор
|
Пост N: 4007
Зарегистрирован: 23.05.05
|
|
Отправлено: 09.03.21 09:02. Заголовок: Можно просто сделать..
Можно просто сделать класс средствами ООП с нужной структурой. Но ординарного значения объект этого класса иметь не будет HB_IT_ENUM - это отдельный тип специально для цикла for each, повторить это не получится Там даже переменная этого типа используется и передается другим функциям через процедуру unref, где вместо типа enum подставляется ординарный тип
|
|
|
|
| |
Пост N: 298
Зарегистрирован: 05.10.06
|
|
Отправлено: 09.03.21 09:35. Заголовок: Pasha пишет: повтор..
Pasha пишет: цитата: | повторить это не получится |
| Жаль, мне кажется такой подход имеет хороший потенциал... Много написано в старом стиле clipper, который ограничивает функционал и что бы все переделать нужно потратить много времени, разобраться и переписать на объектную модель. А была бы такая возможность реализовать, можно в функцию которая возвращает значение добавлять нужные свойства, без глобального изменения кода...
|
|
|
|
| постоянный участник
|
Пост N: 3580
Зарегистрирован: 17.02.12
|
|
Отправлено: 09.03.21 09:42. Заголовок: MIKHAIL Посмотрите ..
MIKHAIL Посмотрите в hmg h_objects.prg CLASS TKeyData с методами это объект контейнер в котором можете создавать свою структуру переменных, например Local o := oKeyData() o:cVar1 := "...." o:nVar1 := 12345 o:Set(1, "test1") o:Set(2, "test2") ... ? o:nVar1, o:cVar1, o:Get(1), oGet(2), , o:Get(3, "Default3") ? "All elements as {{key, value}, ...} =", o:GetAll(.F.) AEval(o:GetAll(.F.), {{|a,n| _logfile(n, a[1], a[2]) }) ? ? "All elements as {value, ...} =", o:GetAll(.T.) AEval(o:GetAll(.T.), {{|x,n| _logfile(n, x) }) ? Если переменной объекта нет, возвращает Nil или что стоит во 2м параметре o:Get(xKey, xDef) Можно сделать ф-ии для работы с public переменными *----------------------------------------------------------------------------* FUNCTION oPubGet( cVar, cVarName, xDef ) *----------------------------------------------------------------------------* Default cVarName := "m_Container" RETURN __mvGet( cVarName ):Get( upper(cVar), xDef ) *----------------------------------------------------------------------------* FUNCTION oPubSet( cVar, xVal, cVarName ) *----------------------------------------------------------------------------* Default cVarName := "m_Container" RETURN __mvGet( cVarName ):Set( upper(cVar), xVal ) делать PUBLIC m_Container := oKeyData()
|
|
|
|
| |
Пост N: 299
Зарегистрирован: 05.10.06
|
|
Отправлено: 09.03.21 10:19. Заголовок: SergKis Это обычные..
SergKis Это обычные объекты, то о чем и писал Pasha, сам объект не будет иметь ординарного значения. Реализаций много, но это связано с глобальной перепиской кода... Меня заинтересовал именно тот момент, что в конструкции for each var, var - имеет собственное значение и можно получить некий набор свойств...но увы
|
|
|
|
| постоянный участник
|
Пост N: 3581
Зарегистрирован: 17.02.12
|
|
Отправлено: 09.03.21 10:27. Заголовок: MIKHAIL пишет что в ..
MIKHAIL пишет цитата: | что в конструкции for each var, var - имеет собственное значение и можно получить некий набор свойств |
| Не так однозначно и не ясно зачем, т.к. for each var, var1, var2, var3 in aVar, aVar2, cVar3
|
|
|
|
| Администратор
|
Пост N: 4008
Зарегистрирован: 23.05.05
|
|
Отправлено: 09.03.21 11:52. Заголовок: Для объектов класса ..
Для объектов класса можно переопределить арифметические/логические операции. Можно переопределить даже присваивание, т.е. assign Можно динамически добавлять свойства и методы. Но значение переменной объекта переопределить нельзя Если o - объект, то выражение <var> := o будет возвращать сам объект, а не некое значение
|
|
|
|
|
| постоянный участник
|
Пост N: 3583
Зарегистрирован: 17.02.12
|
|
Отправлено: 09.03.21 13:17. Заголовок: MIKHAIL пишет сам об..
MIKHAIL пишет цитата: | сам объект не будет иметь ординарного значения. Реализаций много, но это связано с глобальной перепиской кода... |
| CLASS TKeyData это обвязка Hash контейнера, потому может исп. как разные структуры данных с доступом к hash данным через именованный ключ, как к переменной объекта. При этом можете наследовать TKeyData и расширять возможности свойств полученного объекта, если надо, но можно обходится и ф-ями, передавая ссылку на объект-контейнер. Например работа с записью o1 := (cAls1)->( oRecGet() ) o := (cAls)->( oRecGet() ) o:Field1 := "..." o:Field2 := 12345 o:Field3 += nSum o1:Field3 := o:Field3 + o:Field4 ... (cAls)->( oRecPut( o ) ) (cAls1)->( oRecPut( o1 ) ) ф-ии Скрытый текст
*----------------------------------------------------------------------------* FUNCTION oRecGet( aField, oRec ) *----------------------------------------------------------------------------* LOCAL cFld, nPos Default oRec := oKeyData() IF ISCHAR(aField) IF left(aField, 1) == "{" .and. right(aField, 1) == "}" aField := &aField ELSE aField := hb_ATokens(aField, ",") ENDIF ENDIF IF ISARRAY(aField) FOR EACH cFld IN aField IF Empty( cFld ) ; LOOP ELSEIF ISARRAY(cFld) ; cFld := cFld[1] // массив как структура ENDIF IF ( nPos := FieldPos(cFld) ) > 0 oRec:Set( trim(FieldName(nPos)), FieldGet(nPos) ) ENDIF NEXT ELSE AEval( Array( FCount() ), {|v,n| v:=n, oRec:Set( trim(FieldName(n)), FieldGet(n) ) } ) ENDIF RETURN oRec *----------------------------------------------------------------------------* FUNCTION oRecPut( oRec, aField ) *----------------------------------------------------------------------------* LOCAL aFld, cFld, nPos, xVal, nCnt := 0 IF ISCHAR( aField ) IF left(aField, 1) == "{" .and. right(aField, 1) == "}" aField := &aField ELSE aField := hb_ATokens(aField, ",") ENDIF ENDIF IF ISARRAY( aField ) FOR EACH cFld IN aField IF Empty( cFld ) ; LOOP ELSEIF ISARRAY(cFld) ; cFld := cFld[1] // массив как структура ENDIF cFld := upper(trim( cFld )) xVal := oRec:Get( cFld ) IF xVal == NIL ; LOOP ENDIF IF ( nPos := FieldPos(cFld) ) > 0 IF FieldType( nPos ) $ "+^="; LOOP // защита записи ENDIF FieldPut( nPos, xVal ) nCnt++ ENDIF NEXT ELSE FOR EACH aFld IN oRec:GetAll(.F.) cFld := aFld[1] IF aFld[2] == NIL ; LOOP ENDIF IF ( nPos := FieldPos(cFld) ) > 0 IF FieldType( nPos ) $ "+^="; LOOP // защита записи ENDIF FieldPut( nPos, aFld[2] ) nCnt++ ENDIF NEXT ENDIF RETURN nCnt > 0
|
|
|
|
|
| постоянный участник
|
Пост N: 3584
Зарегистрирован: 17.02.12
|
|
Отправлено: 09.03.21 13:35. Заголовок: PS Если есть relatio..
PS Если есть relation с документов на справочник, можно делать o := (cAlsSpr)->( oGetRec() ) o := (cAls)->( oGetRec( , o) ) получим в объекте все поля с разных алиасов, причем совпавшие поля по именам будут иметь значения с пос. алиас, т.е. документов
|
|
|
|
| |
Пост N: 300
Зарегистрирован: 05.10.06
|
|
Отправлено: 09.03.21 13:42. Заголовок: SergKis пишет: Не т..
SergKis пишет: цитата: | Не так однозначно и не ясно зачем, т.к. for each var, var1, var2, var3 in aVar, aVar2, cVar3 |
| речь не о for each, а подход который там реализован в части : __enum* SergKis объектная модель хороша, спору нет, просто интересное решение когда переменная имеет и собственное ординарное значение и дает возможность получать ссылки на свойства этой переменой Pasha пишет: цитата: | <var> := o будет возвращать сам объект, а не некое значение |
| это понятно...
|
|
|
|
| постоянный участник
|
Пост N: 3585
Зарегистрирован: 17.02.12
|
|
Отправлено: 09.03.21 13:55. Заголовок: MIKHAIL пишет дает в..
MIKHAIL пишет цитата: | дает возможность получать ссылки на свойства этой переменой |
| Не оч. понятно, что имеете ввиду, если данные из внутренней таблицы hb, описывающей, структуру переменной (public, private,...), то на уровне hb такие C ф-ии должны быть.
|
|
|
|
| |
Пост N: 301
Зарегистрирован: 05.10.06
|
|
Отправлено: 09.03.21 14:07. Заголовок: SergKis Pasha пишет:..
SergKis Pasha пишет: цитата: | для этого введен отдельный тип данных: enum. На prg уровне для var нет различия между регулярным типом и enum. Но на уровне C для хранения var а HB_ITEM используется отдельная структура: enum, которая содержит ссылку на элемент массива, и дает доступ к свойствам типа __enumIndex, __enumStart и пр. ... HB_IT_ENUM - это отдельный тип специально для цикла for each, повторить это не получится |
|
|
|
|
|
| постоянный участник
|
Пост N: 3586
Зарегистрирован: 17.02.12
|
|
Отправлено: 09.03.21 14:14. Заголовок: MIKHAIL пишет речь н..
MIKHAIL пишет или все таки о for each ... или hash подойдет aHash := hb_hEval( aHash, bBlock, [nStart], [nCount] ) Выполняет кодоблок для каждой пары массива aHash, кодоблоку передаются ключ, значение и индекс.
|
|
|
|
| |
Пост N: 302
Зарегистрирован: 05.10.06
|
|
Отправлено: 09.03.21 14:39. Заголовок: SergKis пишет: или ..
SergKis пишет: цитата: | или все таки о for each ... или hash подойдет |
| Нет, Pasha уже написал что не повторить такую конструкцию в HB Смысл в том что в for each реализована похожая на объектную модель схема, где у переменной var есть собственное значение и есть свойства, доступ к которым через свойства var:__enumindex и другие... В объектной модели, переменная, которой присвоен объект, ссылается на объект и не имеет своего значения, все это выше уже обсуждалось. Понятно что это можно заменить разными решениями, просто мне понравилась именно такая реализация...
|
|
|
|
| постоянный участник
|
Пост N: 1595
Зарегистрирован: 09.10.06
|
|
Отправлено: 10.03.21 00:57. Заголовок: MIKHAIL пишет: В об..
MIKHAIL пишет: цитата: | В объектной модели, переменная, которой присвоен объект, ссылается на объект и не имеет своего значения |
| Это не относится к скалярным классам. цитата: | #include "hbclass.ch" PROCEDURE Main() LOCAL aDim, e LOCAL nVar0 := 2, nVarN := 3 ENABLE TYPE CLASS ALL aDim := { {1,2,3},; {||Qout("A")},; "String",; Date(),; {"A"=>1},; .T.,; 100,; hb_StrToTS("2021-03-02 01:12:13.10"),; @Mul(),; Nil} FOR EACH e IN aDim ? e:ClassName(), [ >> ], e:AsString() NEXT ASSOCIATE CLASS MyNumericClass WITH TYPE NUMERIC ? nVar0 ? nVarN ? nVar0 += nVarN ? nVar0 += "100" ? nVar0 *= "100" ? nVarN:AsString(), "*", nVar0:AsString(), "==", Mul(nVar0, nVarN):AsString() RETURN FUNCTION Mul(a, b) RETURN a*b CLASS MyNumericClass FROM __HBNumeric OPERATOR "+" ARG xArg INLINE ( Self := Self + Val(xArg) ) OPERATOR "*" ARG xArg INLINE ( Self := Self * Val(xArg) ) END CLASS |
|
|
|
|
|
| |
Пост N: 303
Зарегистрирован: 05.10.06
|
|
Отправлено: 10.03.21 15:58. Заголовок: Петр пишет: Это не ..
Петр пишет: цитата: | Это не относится к скалярным классам |
| Не вполне понял пример, поясните пож-ста, кое что мне не знакомо: ENABLE TYPE CLASS ALL - ? e:ClassName(), e:AsString() - что за методы, откуда они беруться ? [ >> ] - что за оператор ? ASSOCIATE CLASS MyNumericClass WITH TYPE NUMERIC - что означает начало и концовка выражения ? и как переменные и операции связаны с этим классом ? FROM __HBNumeric - ? где можно получить более подробную информацию о скалярных классах ?
|
|
|
Ответов - 21
, стр:
1
2
All
[только новые]
|
|