Ошибка при работе с TCollection и TCollectionItem

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ошибка при работе с TCollection и TCollectionItem

Сообщение bloodlines » 23.10.2009 10:41:42

По аналогии с TDBF модулем DBF_Fields пишу для своих нужд BTRFIELDS.

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

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type

{ TBtrFieldDef }

TBtrFieldType = (

btrAUTOINC2,btrAUTOINC4,btrBFLOAT4,btrBFLOAT8,btrBFLOAT,btrBIGINT,btrBIT,btrBLOB,btrCHAR,
btrCLOB,btrCURRENCY,btrDATE,btrDATETIME,btrDECIMAL,btrDOUBLE,btrFLOAT4,btrFLOAT8,btrGUID,
btrIDENTITY,btrINTEGER1,btrINTEGER2,btrINTEGER4,btrINTEGER8,btrINTEGER,btrLOGICAL,btrLOGICAL2,
btrLONGVARBINARY,btrLONGVARCHAR,btrMONEY,btrNUMERIC,btrNUMERICSA,btrNUMERICSLB,btrNUMERICSLS,
btrNUMERICSTB,btrNUMERICSTS,btrREAL,btrSMALLIDENTITY,btrSMALLINT,btrSTRING,btrTIME,btrTIMESTAMP,
btrTINYINT,btrUBIGINT,btrUINTEGER,btrUNIQUEIDENTIFIER,btrUNSIGNED_BINARY,btrUNSIGNED1_BINARY,
btrUNSIGNED2_BINARY,btrUNSIGNED4_BINARY,btrUNSIGNED8_BINARY,btrUSMALLINT,btrUTINYINT,btrVARCHAR,
btrWSTRING,btrWSZSTRING,btrWZSTRING,btrZSTRING

  );

TBtrFieldDef = class(TCollectionItem)
  private
    FFieldName: string;
    FFieldType: TBtrFieldType;
    FSize: Integer;
    FPrecision: Integer;

    procedure SetSize(lSize: Integer);
    procedure SetPrecision(lPrecision: Integer);
    procedure SetFieldType(lFieldType: TBtrFieldType);

  protected

  public
    FieldValue:string;

    constructor Create(ACollection: TCollection); override;
    destructor Destroy; override;

    procedure SetDefaultSize;

  published
    property FieldName: string     read FFieldName write FFieldName;
    property FieldType: TBtrFieldType read FFieldType write SetFieldType;
    property Size: Integer         read FSize      write SetSize;
    property Precision: Integer    read FPrecision write SetPrecision;
    property Value:string read FieldValue write FieldValue;
  end;

  { TBtrFieldDefs }

  TBtrFieldDefs = class(TCollection)
  private
    FOwner: TPersistent;

    function GetItem(Idx: Integer): TBtrFieldDef;
  protected
    function GetOwner: TPersistent; override;
  public
    constructor Create(BOwner: TPersistent);

{$ifdef SUPPORT_DEFAULT_PARAMS}
    procedure Add(const Name: string; DataType: TBtrFieldType; Size: Integer = 0);
{$else}
    procedure Add(const Name: string; DataType: TBtrFieldType; Size: Integer);
{$endif}
    function AddFieldDef: TBtrFieldDef;

    property Items[Idx: Integer]: TBtrFieldDef read GetItem;
    //function FieldByName(FName)
  end;

implementation

procedure TBtrFieldDef.SetDefaultSize;
begin
  // choose default values for variable size fields
  case FFieldType of

     btrINTEGER1, btrUNSIGNED1_BINARY, btrLOGICAL, btrBIT, btrTINYINT, btrUTINYINT  :
      begin
        FSize := 1;
        FPrecision := 0;
      end;

     btrAUTOINC2, btrINTEGER2, btrUNSIGNED2_BINARY, btrLOGICAL2, btrSMALLIDENTITY, btrSMALLINT, btrUSMALLINT :
      begin
        FSize := 2;
        FPrecision := 0;
      end;

     btrAUTOINC4, btrBFLOAT4, btrDATE, btrFLOAT4, btrINTEGER4, btrTIME, btrUNSIGNED4_BINARY, btrIDENTITY,
     btrREAL, btrINTEGER, btrUINTEGER :
      begin
        FSize := 4;
        FPrecision := 0;
      end;

     btrBFLOAT8, btrCURRENCY, btrDATETIME, btrFLOAT8, btrINTEGER8, btrTIMESTAMP, btrUNSIGNED8_BINARY,
     btrDOUBLE, btrBIGINT, btrUBIGINT :
      begin
        FSize := 8;
        FPrecision := 0;
      end;
      //&&&!!!!!!????
     btrGUID, btrUNIQUEIDENTIFIER :
      begin
        FSize := 16;
        FPrecision := 0;
      end;

     btrNUMERIC, btrNUMERICSA, btrNUMERICSLB, btrNUMERICSLS, btrNUMERICSTB, btrNUMERICSTS :
      begin
        FSize := 37;
        FPrecision := 0;
      end;

     btrDECIMAL :
      begin
        FSize := 64;
        FPrecision := 0;
      end;

     btrSTRING, btrZSTRING, btrVARCHAR, btrCHAR :
      begin
        FSize := 8000;
        FPrecision := 0;
      end;

  end;
end;

function TBtrFieldDefs.GetItem(Idx: Integer): TBtrFieldDef;
begin
  Result := TBtrFieldDef(inherited GetItem(Idx));
end;

constructor TBtrFieldDefs.Create(BOwner: TPersistent);
begin
  inherited Create(TBtrFieldDef);
  FOwner := BOwner;
end;

function TBtrFieldDefs.AddFieldDef: TBtrFieldDef;
begin
  Result := TBtrFieldDef(inherited Add);
end;

function TBtrFieldDefs.GetOwner: TPersistent; {override;}
begin
  Result := FOwner;
end;

procedure TBtrFieldDefs.Add(const Name: string; DataType: TBtrFieldType; Size: Integer);
var
  FieldDef: TBtrFieldDef;
begin
  FieldDef := AddFieldDef;
  FieldDef.FieldName := Name;
  FieldDef.FieldType := DataType;
  if Size <> 0 then
    FieldDef.Size := Size;
end;

constructor TBtrFieldDef.Create(ACollection: TCollection); {virtual}
begin
  inherited;
  FPrecision := 0;
end;

destructor TBtrFieldDef.Destroy; {override}
begin
  inherited;
end;

procedure TBtrFieldDef.SetFieldType(lFieldType: TBtrFieldType);
begin
  FFieldType := lFieldType;
  SetDefaultSize;
end;

procedure TBtrFieldDef.SetSize(lSize: Integer);
begin
  FSize := lSize;
end;

procedure TBtrFieldDef.SetPrecision(lPrecision: Integer);
begin
  FPrecision := lPrecision;
end;

end.



В основном код ещё сырой и не отлаженный. На данный момент меня интересует реализация метода
Код: Выделить всё
TBtrFieldDefs.Add


При попытке его вызова
Код: Выделить всё
var
BTR:TBTRFielddefs;

BTR.Add('Test', btrChar, 1);

Возникает ошибка в строке
Код: Выделить всё
Result := TBtrFieldDef(inherited Add);


В чём может быть ошибка, куда копать?
Аватара пользователя
bloodlines
постоялец
 
Сообщения: 100
Зарегистрирован: 05.11.2008 11:26:19

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение Mr.Smart » 23.10.2009 10:53:05

inherited вызывает наследуемый override метод родителя. У вас метод Add не наследуемый, а собственный метод класса.
Уберите inherited :wink:
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение bloodlines » 23.10.2009 11:28:49

Что то я слегка запутался. Суть моего вопроса сводиться к добавлению в коллекцию BTRFieldDefs нового элемента BTRFieldDef. Собственно при вызове метода
Код: Выделить всё
Add
должен создаваться новый экземпляр класса BTRFieldDef и добавляться к BTRFieldDefs. Подскажите как это сделать, а то никак не могу сообразить.
Аватара пользователя
bloodlines
постоялец
 
Сообщения: 100
Зарегистрирован: 05.11.2008 11:26:19

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение Mr.Smart » 23.10.2009 13:02:10

Код: Выделить всё
Result := TBtrFieldDef(Add);
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение bloodlines » 23.10.2009 13:30:50

При таком раскладе ругается
btrfields.pas(150,29) Error: Wrong number of parameters specified for call to "Add"
btrfields.pas(69,15) Hint: Found declaration: TBtrFieldDefs.Add(const AnsiString,TBtrFieldType,LongInt);
btrfields.pas(198) Fatal: There were 1 errors compiling module, stopping

Прикрепил к сообщению архив с тестовым проектом.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
bloodlines
постоялец
 
Сообщения: 100
Зарегистрирован: 05.11.2008 11:26:19

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение diman169 » 23.10.2009 13:56:19

при объявлении дефайны проверяются
{$ifdef SUPPORT_DEFAULT_PARAMS}

а в implementation части не видно...
diman169
незнакомец
 
Сообщения: 5
Зарегистрирован: 23.10.2009 13:45:03

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение bloodlines » 23.10.2009 14:11:42

Если убрать из исходника
Код: Выделить всё
{$ifdef SUPPORT_DEFAULT_PARAMS}

то ошибка остаётся такой же и никуда не пропадает.
Аватара пользователя
bloodlines
постоялец
 
Сообщения: 100
Зарегистрирован: 05.11.2008 11:26:19

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение diman169 » 23.10.2009 14:30:42

верни inherited назад
Result := TBtrFieldDef(inherited Add);
как было, и сообщи какая ошибка выдается.

без inherited вызывается метод твоего объекта, в котором должны быть параметры (const Name: string; DataType: TBtrFieldType; Size: Integer)
но ставить их не надо, т.к. Add и AddFieldDef будут бесконечно вызывать друг друга
diman169
незнакомец
 
Сообщения: 5
Зарегистрирован: 23.10.2009 13:45:03

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение v-t-l » 23.10.2009 14:38:20

Код: Выделить всё
Result := TBtrFieldDef(Add(Здесь должны быть параметры));
v-t-l
энтузиаст
 
Сообщения: 740
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение diman169 » 23.10.2009 14:48:54

не дождался, скачал архив, вставил inherited
Result := TBtrFieldDef(inherited Add);
компилится без проблем
diman169
незнакомец
 
Сообщения: 5
Зарегистрирован: 23.10.2009 13:45:03

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение v-t-l » 23.10.2009 14:53:47

посмотрел сырцы
Add и AddFieldDef вызывают друг друга.
лучше TBtrFieldDef(inherited Add) вызывать в переопределенном методе TBtrFieldDefs.Add
v-t-l
энтузиаст
 
Сообщения: 740
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение bloodlines » 23.10.2009 14:57:39

компилится без проблем

Запусти и нажми на кнопку. Будет ошибка.

и сообщи какая ошибка выдается

Acces Violation.
Add и AddFieldDef будут бесконечно вызывать друг друга

Вот вот! Это то я понимаю!
Уважаемые! Единственное что мне сейчас нужно, это понят как создать новый элемент коллекции TBTRFieldDef и добавить его к коллекции BTRFieldDefs
Код: Выделить всё
procedure TBtrFieldDefs.Add(const Name: string; DataType: TBtrFieldType; Size: Integer);
var
  FieldDef: TBtrFieldDef;
begin
   ////
   // Здесь создаём TBtrFieldDef и добавляем его в коллекцию.
////
  FieldDef.FieldType := DataType;
  if Size <> 0 then
    FieldDef.Size := Size;
end;

Вот блин! У TDBF это ж каким то макаром работает!
Аватара пользователя
bloodlines
постоялец
 
Сообщения: 100
Зарегистрирован: 05.11.2008 11:26:19

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение v-t-l » 23.10.2009 15:01:37

Попробуй TBtrFieldDef(inherited Add) вызывать в переопределенном методе TBtrFieldDefs.Add,
а в AddFieldDef вызывай Add с параметрами.
v-t-l
энтузиаст
 
Сообщения: 740
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение bloodlines » 23.10.2009 15:07:04

Попробуй TBtrFieldDef(inherited Add) вызывать в переопределенном методе TBtrFieldDefs.Add,
а в AddFieldDef вызывай Add с параметрами.

Ничего хорошего не получилось - по моему получилось зацикливание - методы друг на друга ссылаются. К сообщению прикрепил архив с файлом dbf_fields.pas возможно пригодиться - я по аналогии делал.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
bloodlines
постоялец
 
Сообщения: 100
Зарегистрирован: 05.11.2008 11:26:19

Re: Ошибка при работе с TCollection и TCollectionItem

Сообщение v-t-l » 23.10.2009 15:09:34

Кстати, а почему Add переопределена как процедура?
v-t-l
энтузиаст
 
Сообщения: 740
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13

Рейтинг@Mail.ru