Автор | Сообщение |
|
| |
Пост 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 - ? где можно получить более подробную информацию о скалярных классах ?
|
|
|
|
| постоянный участник
|
Пост N: 1597
Зарегистрирован: 09.10.06
|
|
Отправлено: 10.03.21 17:21. Заголовок: ### SCALAR CLASSE..
цитата: | ### SCALAR CLASSES ### ============================ Both compilers support scalar classes and allows to add OOP functionality to native types like numeric, character, array, hash, codeblock, date, ... It's possible to overload default scalar classes provided by Harbour and xHarbour or use ASSOCIATE CLASS command to bound any class with some native type. It's also possible to overload the behavior of some operators if it's not already defined for given types. Anyhow it's not possible to change operator precedence which is the same for all types and defined at compile time. |
| Команда ENABLE TYPE CLASS ALL разрешает ООП функциональность для ВСЕХ (ALL) скалярных типов, поддерживаемых Hb. Можно было бы написать ENABLE TYPE CLASS NUMERIC но в первой части примера я показал, что все типы (ну еще есть указатель, кроме перечисленных) имеют, как минимум, один метод AsString унаследованный от ScalarObject. Рекомендую изучить исходник src\rtl\tscalar.prg В т.ч. информацию по ссылке /* Class(y) documentation is located at: https://harbour.github.io/ng/classy/menu.html */ ASSOCIATE CLASS MyNumericClass WITH TYPE NUMERIC это означает, что мы ассоциировали класс MyNumericClass (унаследованный от класса Numeric) с числовым типом и Hb при операциях с числовым типом будет использовать свойства (операторы/методы) этого класса. [ >> ] == " >> " - просто строка для вывода QOut MIKHAIL пишет: цитата: | что означает начало и концовка выражения ? |
| Уточните какого именно.
|
|
|
Ответов - 21
, стр:
1
2
All
[только новые]
|
|