Индексирование объектов

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
iBAH
Бывалый
Сообщения: 56
Зарегистрирован: 14 Январь 2006, 13:44
Откуда: Ярославль
Контактная информация:

Индексирование объектов

Сообщение iBAH »

Хочу создать объектную модель для вывода данных в таблицы аля document.Tables[n].Cells[i,j]...
но к сожалению Клара не дает создавть масиивы обектов :(
попробовал пользоваться методами моих классов следующим образом: document.Tables(n).Cells(i,j); классы и подклассы лежали в очередях... и снова Клара не дает возвращать указатель на объект... Люди добрые подскажите как лучше индексировать объекты, а то все время делать GET(document.TablesQ, n) и т. д. как то не прикольно, да и код реально нечитабельный становится
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Re: Индексирование объектов

Сообщение StillZero »

iBAH писал(а):Хочу создать объектную модель для вывода данных в таблицы аля document.Tables[n].Cells[i,j]...
skip
Люди добрые подскажите как лучше индексировать объекты, а то все время делать GET(document.TablesQ, n) и т. д. как то не прикольно, да и код реально нечитабельный становится
не совсем понял о чем речь...
понял так:

есть класс DocumentClass
надо чтобы много объектов этого класса

делаем очередь

Код: Выделить всё

DocumentsObjectQueue QUEUE,TYPE
ID                                   LONG
Ref                                 &DocumentClass
                                    END
делаем еще один класс

Код: Выделить всё

DocumentManagerClass CLASS
DO                                  &DocumentsObjectQueue ! ссылка на очередь объектов
AddDocument                   PROCEDURE ! добавить документ
GetDocument                   PROCEDURE  ! взять документ
RemoveDocument             PROCEDURE ! удалить 
                                    END
т.е. вместо get(Queue,obj) будем юзать .GetDocument
Аватара пользователя
Andrew™
SQL профи
Сообщения: 651
Зарегистрирован: 05 Июль 2005, 16:32
Откуда: Москва, Зеленоград

Re: Индексирование объектов

Сообщение Andrew™ »

iBAH писал(а):Хочу создать объектную модель для вывода данных в таблицы аля document.Tables[n].Cells[i,j]...
но к сожалению Клара не дает создавть масиивы обектов :(
попробовал пользоваться методами моих классов следующим образом: document.Tables(n).Cells(i,j); классы и подклассы лежали в очередях... и снова Клара не дает возвращать указатель на объект... Люди добрые подскажите как лучше индексировать объекты, а то все время делать GET(document.TablesQ, n) и т. д. как то не прикольно, да и код реально нечитабельный становится
храни адреса объектов, обычные LONG'и, а преобразование к объекту оченть простое

tmp &myObject

tmp &= (LONG)
iBAH
Бывалый
Сообщения: 56
Зарегистрирован: 14 Январь 2006, 13:44
Откуда: Ярославль
Контактная информация:

Re: Индексирование объектов

Сообщение iBAH »

StillZero писал(а): не совсем понял о чем речь...
понял так:
есть класс DocumentClass
надо чтобы много объектов этого класса
делаем очередь
...
делаем еще один класс
...
т.е. вместо get(Queue,obj) будем юзать .GetDocument
вы все верно поняли...
Все делал именно так, как указано выше:
Tables PROCEDURE(BYTE NTable) - метод класса TableClass
в методе выбираю из кьюхи соответсвующую запись и запоминаю ее объект в переменную(CurObject &myObject )... и т. д. аналогично со всеми классами...
НО... по скольку у меня иерархическая структура, которая может содержать такие же стуктуры, т.е. documents.tables.cells[i,j].documents... (короче в ячейке таблицы может храниться еще документ с таблицей и т. д.)... становится не очень удобно пользоваться этим классом, и к тому же мне не нравится сообщение между классами через посредника, а именно перемнную с адресом...

Хочу добиться доступа к любому объекту через одну строку...как описывал выше.

Здесь возникает вопрос:
Можно ли прописать в классе метод так, чтобы он возвращал указатель на объект, т.е. может это делается так

Код: Выделить всё

MyClass2 CLASS,TYPE
MyMethod PROCEDURE(...), *MyClass1
END
... или может как то иначе... и как в дальнейшем мне получить возврщенный указатель(объект)... Class1Obj &MyClass1... Class1Obj&=Class2Obj.MyMethod - так ведь в данном случае не покатит... ???
В случае, если делаю экземпляр и присваиваю ему адресс:

Код: Выделить всё

Class1Obj MyClass1

Class1Obj=address(Class2Obj.MyMethod)
все работает, но тем не менее программа ругается при закрытии... в чем дело?

ЗЫ documents.tables.cells[i,j] - пишу так по привычке, подобно структуре HTML документа, и к тому же класс потом генерит HTML.
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

вообщем то ... все равно сумбурно, не укладывается в голове, вот пример:

Код: Выделить всё

 PROGRAM
 MAP
 END

DocumentClass CLASS,TYPE                   ! документ
MyProp           LONG                      ! свойство документа
              END

DocumentQueue QUEUE,TYPE                   ! очередь документов
ID               LONG                      ! какой то ID
Document         &DocumentClass            ! объект-документ
              END

CurrentDoc    &DocumentClass               ! текущий документ (с которым работаем)

DocumentMng   CLASS,TYPE                   ! класс "управление документами"
DQ               &DocumentQueue            ! очередь документов
Construct        PROCEDURE
Destruct         PROCEDURE
AddDocument      PROCEDURE(LONG inID),LONG ! добавление документа, возвращает адрес добавленного документа
              END

DM            DocumentMng                  ! объект "управление документами"

 code
 CurrentDoc &= DM.AddDocument(1)

 if CurrentDoc &= NULL then message('НЕ СОЗДАЛСЯ ОБЪЕКТ').
 if NOT CurrentDoc &= NULL                 ! далее по коду надо везде проверять на NOT NULL
    message(CurrentDoc.MyProp)
 end
! **************************************************************
DocumentMng.Construct   PROCEDURE
 code
 SELF.DQ &= new DocumentQueue              ! создаем очередь документов
! **************************************************************
DocumentMng.Destruct   PROCEDURE
 code
 if NOT SELF.DQ &= NULL                    ! убиваем очередь и убиваем все классы
    loop j# = 1 to records(SELF.DQ)
       get(SELF.DQ,j#)
       if NOT SELF.DQ.Document &= NULL
          dispose(SELF.DQ.Document)
       end
    end
    dispose(SELF.DQ)
 end
! **************************************************************
DocumentMng.AddDocument PROCEDURE(LONG inID)
 code
 SELF.DQ.ID = inID                        ! добавление документа в очередь
 get(SELF.DQ, SELF.DQ.ID)
 if errorcode()
    SELF.DQ.ID = inID
    SELF.DQ.Document &= new DocumentClass
    add(SELF.DQ)
 end
 SELF.DQ.Document.MyProp = 10
 return address(SELF.DQ.Document)         ! возвращаем адрес объекта
вообще Мялин Андрей показал, как зная адрес объекта получить сам объект, правда это выглядит неочевидно...главное в этом деле скобки ().

т.е. допустим такая ситуация:
MyClass CLASS.
ObjectAddress LONG
Object &MyClass

ObjectAddress = address(MyClass) ! узнали адрес объекта
Object &= (ObjectAddress) ! "приравняли" оъекты, т.е. теперь Object ссылается на MyClass
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

documents.tables.cells[i,j]


объяснили тут мне...наконец таки :( ... что ты хочешь - удобной записи

я думаю, это НЕВОЗМОЖНО сделать
на самый край получится вызов метода, что то вроде
.GetObject(1,2,3,4)
или вызов цепочки методов
.GetDoc(1)
.GetTable(2)
.GetCell(3,4)
а это все равно нечитабельно

если реализуешь пиши, интересно
удачи :)
Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

задело меня конечно, что говорить, Mixer-а притянул... вообщем можно все сделать :)

Код: Выделить всё

 PROGRAM
 MAP
 END

DocumentsQueue QUEUE,TYPE
ID                LONG
D                 &Document
               END

TablesQueue    QUEUE,TYPE
ID                LONG
T                 &Table
               END

HTMLClass      CLASS,TYPE
Documents         &Documents
Document          &Document
Init              PROCEDURE
               END

Documents      CLASS(HTMLClass),TYPE
PC                &HTMLClass
DQ                &DocumentsQueue
Init              PROCEDURE(HTMLClass PC)
Kill              PROCEDURE
AddDocument       PROCEDURE(LONG inID)
ActivateDocument  PROCEDURE(LONG inID)
               END

Document       CLASS,TYPE
URL               STRING(100)
Tables            &Tables
Table             &Table
Init              PROCEDURE
               END

Tables         CLASS(Document),TYPE
PC                &Document
TQ                &TablesQueue
Init              PROCEDURE(Document PC)
Kill              PROCEDURE
AddTable          PROCEDURE(LONG inID)
ActivateTable     PROCEDURE(LONG inID)
               END

Table          CLASS,TYPE
Caption           STRING(100)
Border            BYTE(0)
Width             STRING(6)
               END

HTML           HTMLClass

 code
 HTML.Init
 HTML.Documents.AddDocument(1)
 HTML.Document.URL = 'http://click.com'
 HTML.Document.Tables.AddTable(1)
 HTML.Document.Table.Caption = 'test table'
 HTML.Document.Tables.AddTable(2)
 HTML.Document.Table.Caption = 'test table1'

 message(HTML.Document.URL)

 HTML.Document.Tables.ActivateTable(1)
 message(HTML.Document.Table.Caption)

 HTML.Document.Tables.ActivateTable(2)
 message(HTML.Document.Table.Caption)
!===============================================================================
HTMLClass.Init              PROCEDURE
 code
 SELF.Documents &= NEW Documents
 SELF.Documents.Init(SELF)
!===============================================================================
Documents.Init      PROCEDURE(HTMLClass PC)
 CODE
 SELF.DQ &= new DocumentsQueue
 SELF.PC &= PC
!-------------------------------------------------------------------------------
Documents.Kill PROCEDURE
 code
 dispose(SELF.DQ)
!-------------------------------------------------------------------------------
Documents.AddDocument       PROCEDURE(LONG inID)
 code
 SELF.DQ.ID = inID
 SELF.DQ.D &= new Document
 SELF.DQ.D.Init
 add(SELF.DQ)
 SELF.ActivateDocument(inID)
!-------------------------------------------------------------------------------
Documents.ActivateDocument  PROCEDURE(LONG inID)
 code
 SELF.DQ.ID = inID
 get(SELF.DQ,SELF.DQ.ID)
 SELF.PC.Document &= SELF.DQ.D
!===============================================================================
Document.Init               PROCEDURE
 code
 SELF.Tables &= NEW Tables
 SELF.Tables.Init(SELF)
!===============================================================================
Tables.Init                 PROCEDURE(Document PC)
 CODE
 SELF.TQ &= new TablesQueue
 SELF.PC &= PC
!-------------------------------------------------------------------------------
Tables.Kill PROCEDURE
 code
 dispose(SELF.TQ)
!-------------------------------------------------------------------------------
Tables.AddTable             PROCEDURE(LONG inID)
 code
 SELF.TQ.ID = inID
 SELF.TQ.T &= new Table
 add(SELF.TQ)
 SELF.ActivateTable(inID)
!-------------------------------------------------------------------------------
Tables.ActivateTable        PROCEDURE(LONG inID)
 code
 SELF.TQ.ID = inID
 get(SELF.TQ,SELF.TQ.ID)
 SELF.PC.Table &= SELF.TQ.T
!-------------------------------------------------------------------------------

Аватара пользователя
StillZero
Ветеран
Сообщения: 458
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Поблагодарили: 1 раз
Контактная информация:

Сообщение StillZero »

вот еще вдогонку: здесь очень аккуратно надо использовать Construct методы, можно нарваться на типа "рекусию"
iBAH
Бывалый
Сообщения: 56
Зарегистрирован: 14 Январь 2006, 13:44
Откуда: Ярославль
Контактная информация:

Сообщение iBAH »

StillZero писал(а):объяснили тут мне...наконец таки :( ... что ты хочешь - удобной записи
:) слава богу...
StillZero писал(а):задело меня конечно, что говорить, Mixer-а притянул... вообщем можно все сделать...
Код почти как у меня... :) теперь зацените мой (100% рабочий)

Код: Выделить всё

!!!!!!!!!!!!!!!!!!!!!объявим это все безобразие!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PropClass CLASS, TYPE  ! класс с общими свойствами для элементов отчета
Txt    ASTRING ! имя / заголовок / текст
! общие свойства для отчета
BGCOLOR  LONG
HTMLCOLOR PROCEDURE(), STRING
FONT    STRING(30) ! шрифт заголовков / текста   
CFONT   LONG  ! цвет заголовков / текста
Bold    BYTE
Italic  BYTE
SIZEFONT BYTE  ! размер шрифта
SetFont PROCEDURE(<STRING inFONT>, <BYTE inSIZEFONT>, <LONG inCFONT>, <BYTE inBold>, <BYTE inItalic>)
END

ReportContents CLASS(PropClass), TYPE
NTables BYTE ! число объектов
Construct PROCEDURE()  ! констуктор
Destruct  PROCEDURE()
TablesQ &TablesQUEUE
AddTable  PROCEDURE(BYTE NRows, BYTE NCols)
GenHTML PROCEDURE()
Tables PROCEDURE(BYTE NTable)
END

TablesQUEUE QUEUE, TYPE
TableObj &TableClass
END

TableClass CLASS(PropClass), TYPE
NR        BYTE
NC        BYTE
bodrer_wid BYTE !width in pt
RowsQ     &ROWQUEUE
Construct PROCEDURE()      
Destruct  PROCEDURE()
AddRow    PROCEDURE(BYTE NCells)
MergeCells PROCEDURE(BYTE I, BYTE J, BYTE K, BYTE L) ! объединить ячейки (квадрат)
SetHeight PROCEDURE(BYTE I, LONG Hei) ! высота I-ой строки
SetWidth  PROCEDURE(BYTE J, LONG Wid) ! ширина I-ого столбца
Cells     PROCEDURE(BYTE I, BYTE J)
GenHtmlTable PROCEDURE()
END

ROWQUEUE QUEUE, TYPE
Height LONG
CellsQ &CellQUEUE
END

CellQUEUE QUEUE, TYPE
Width LONG
Cell   &CellClass
END

CellClass CLASS(TableClass), TYPE
skip BYTE
vert_merge BYTE
hor_merge BYTE
END

CurRep &ReportContents
CurTable &TableClass
CurCell &CellClass

S STRING(20)
!!!!!!!!!!!!!!методы(правда не все :))!!!!!!!!!
ReportContents.Construct PROCEDURE()
  CODE
  Self.SetFont('Arial', 16, 'color:black', True)
  Self.BGCOLOR = 'color:white'
  self.TablesQ &= new TablesQUEUE
ReportContents.Destruct PROCEDURE()
  CODE
  LOOP I#=1 TO RECORDS(self.TablesQ)
    GET(self.TablesQ, I#)
    dispose(self.TablesQ.TableObj)
  END
  dispose(self.TablesQ)
ReportContents.AddTable  PROCEDURE(BYTE NRows, BYTE NCols)
  CODE
  IF NRows AND NCols THEN
    self.TablesQ.TableObj &= new TableClass
    ADD(self.TablesQ)
    self.TablesQ.TableObj.NR=NRows
    self.TablesQ.TableObj.NC=NCols
    LOOP NR#=1 TO NRows       
      self.TablesQ.TableObj.AddRow(NCols)
    END
    self.NTables+=1
  ELSE
    Message('Не верно заданы параметры таблицы!')
  END
ReportContents.Tables PROCEDURE(BYTE NTable)
  CODE
  GET(self.TablesQ, NTable)
  CurTable&=self.TablesQ.TableObj
TableClass.Construct PROCEDURE()
  CODE
  Self.SetFont('Arial', 12, 'color:black', True, True)
  Self.BGCOLOR = 'color:white'
  self.ROWSQ &= new ROWQUEUE
TableClass.Destruct PROCEDURE()
  CODE
  LOOP I#=1 TO RECORDS(self.ROWSQ)
    GET(self.ROWSQ, I#)
    LOOP J#=1 TO RECORDS(self.ROWSQ.CellsQ)
      GET(self.ROWSQ.CellsQ, J#)
      dispose(self.ROWSQ.CellsQ.Cell)
    END
    dispose(self.ROWSQ.CellsQ)
  END
  dispose(self.ROWSQ)
TableClass.AddRow    PROCEDURE(BYTE NCells)
  CODE
  self.ROWSQ.CellsQ &= new CellQUEUE
  ADD(self.ROWSQ)
  LOOP NC#=1 TO NCells
    self.RowsQ.CellsQ.Cell &= new CellClass
    self.RowsQ.CellsQ.Cell.skip = 0
    ADD(self.ROWSQ.CellsQ)
  END
TableClass.MergeCells PROCEDURE(BYTE I, BYTE J, BYTE K, BYTE L)
  CODE
  LOOP NR#=I TO K
    LOOP NC#=J TO L
      GET(self.Rowsq, NR#)
      GET(self.Rowsq.CellsQ, NC#)
      IF NR#=I AND NC#=J THEN
        self.RowsQ.CellsQ.Cell.vert_merge=K-NR#
        self.RowsQ.CellsQ.Cell.hor_merge=L-NC#
      ELSE
        self.RowsQ.CellsQ.Cell.skip = 1
      END
    END
  END
TableClass.SetHeight PROCEDURE(BYTE I, LONG Hei)
  CODE
  GET(self.RowsQ, I)
  self.RowsQ.Height=Hei
TableClass.SetWidth  PROCEDURE(BYTE J, LONG Wid)
  CODE
  GET(self.RowsQ, 1)
  GET(self.RowsQ.CellsQ,J)
  self.RowsQ.CellsQ.Width=Wid
TableClass.Cells     PROCEDURE(BYTE I, BYTE J)
  CODE
  GET(self.RowsQ, I)
  GET(self.RowsQ.CellsQ,J)
  CurCell&=self.RowsQ.CellsQ.Cell
А вот так я с ним работаю...

Код: Выделить всё

RC &ReportContents
N SHORT
CODE
RC&=NEW(ReportContents)
RC.Txt='Заголовок отчета'
LOOP N=1 TO 100 ! напечатаем 100 таблиц
  RC.AddTable(8,10) ! создадим таблицу 8*10
  RC.Tables(N)
  CurTable.Txt='Заголовок таблицы '&N
  Message(CurTable.Txt)
  CurTable.MergeCells(1,1,1,2) ! объединение 2 по горизонтали
  CurTable.MergeCells(1,3,2,4)  ! объединение 4-ех
  LOOP I#=5 TO 10
    CurTable.MergeCells(1,I#,2,I#)  ! объединение 2 по вертикали
  END
  LOOP I#=1 TO 8                        
    LOOP J#=1 TO 10
      CurTable.Cells(I#,J#)
      CurCell.Txt='Текст '&I#&'.'&J#
      IF I#<=2 THEN
        CurCell.Bold=True
        CurCell.BGCOLOR=0EFEFEFH
      END
    END
  END
END
RC.GenHTML()
dispose(RC)
по моему вполне читаемо... однако проблема остается...
StillZero писал(а): если реализуешь пиши, интересно
удачи :)
на счет вывода в одну строку у самого большие сомнения...
Кларион позволяет возвращать лишь указатель на класс, т.е. например метод Tables можно записать так:

Код: Выделить всё

Tables PROCEDURE(BYTE NTable), *TableClass
ReportContents.Tables PROCEDURE(BYTE NTable)
  CODE
  GET(self.TablesQ, NTable)
  RETURN(self.TablesQ.TableObj)
но, что дальше... :( address(RC.Tables(i)).Txt так например не дает...
ЗЫ спасибо за внимание :) [/b]
Ответить