Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];

Вниз

Подскажите, как правильно работать со свойствами-массивами   Найти похожие ветки 

 
Константинов ©   (2004-09-23 01:31) [0]

Что-то не очень получается. Выкручиваюсь например так:

MyClass = class ( TPersistent )
private
FList : TList;
public
propertyItems[Index: integer] : TMyObject read GetItem write SetItem;
function Add ( Item : TMyObject ) : integer;
procedure Delete ( Index : integer );
...
//вызов функции Add
var A : TMyClass;
   B : TMyObject;
begin
 A := TMyClass.Create;
 B := TMyObject.Create;
 A.Add(B);
end;

function Add ( Item : TMyObject ) : integer;
var P : ^TMyObject;
begin
GetMem(P,SizeOf(TMyObject));  
 P^ := Item;
 Result := FList.Add(P);
end;

procedure Delete ( Index : integer );
var P : ^TMyObject;
begin
 P := FList[Index];
 P^.Free;
 FList.Delete(Index);
end;

function GetItems ( Index : integer ) : TMyObject;
var P : ^TMyObject;
begin
 P := FList[Index];
 Result := P^;
end;

и т.д. и т.п. эх руки мои кривые...
аш самому глядеть не хочется на такой код.
полез в дебри VCL посмотреть как там это сделано. Нарыл, что используют еще один класс (например TMemoStrings для хранения строк ) и как-то через SendMessage выделяют память под строку где-то в недрах компонента.
Или ( для Font, Pen и т.д. используют TResourceManager, который чрезвычайто замысловато вызывает тот же GetMem

В своем классе мне нужно создать свойство-список классов не компонентов и я не хочу наследоваться от более навороченных классов чем TPersistent

Если можно, самый примитивный примерчик, как корректно реализовать сабж, а то я уже не знаю, где может произойти утечка памяти ( например из-за возникновения исключения не будет вызван Free )

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


 
Defunct ©   (2004-09-23 02:15) [1]

> В своем классе мне нужно создать свойство-список классов не компонентов и я не хочу наследоваться от более навороченных классов чем TPersistent

не совсем понял ваш вопрос, т.е. не понимаю зачем там GetMem и т.п. Посмотрите может поможет такая реализация:

TSignal = class(TDataControl)
Private
 FSignals    : Array of TSignal;
 ...
Protected
 ...
 Function  GetItem(Index: Integer): TSignal;Virtual;
 Procedure SetItem(Index: Integer; Value: TSignal);Virtual;
 ...
Public
 Property    Items[Index: Integer]: TSignal read GetItem write SetItem;
 Property    Count:Integer Read GetCount Write SetCount;
 ...
 Function    Add:TSignal;Virtual;Abstract;
End;

Procedure TSignal.SetItem;
Begin
 Try
   FSignals[Index] := Value;
 Except
   ShowMessage("Wrong index: "+Int2String(Index));
 End;
End;

Function TSignal.GetItem;
Begin
 Try
   Result := FSignals[Index];
 Except
   ShowMessage("Wrong index: "+Int2String(Index));
 End;
End;

Function TSignalGroup.Add;
Begin
 Case ObjectMap.ObjectID Of
   gt_Abstract: FItem := CreateSignal;
   gt_Discrete: FItem := CreateDiscreteSignal;
   gt_Analog:   FItem := CreateAnalogSignal;
   gt_Counter:  FItem := CreateAnalogSignal;
   gt_Control:  FItem := CreateControlSignal;
   Else FItem := CreateSignal;
 End;
 Count := Count + 1;
 SetLength(FSignals, Count);
 FSignals[Count-1] := FItem;
 Result := FItem;
End;


Т.е. как в TList просто выполнять постоянное увеличение числа элементов.


 
Defunct ©   (2004-09-23 02:19) [2]

FItem задан в классе, в котором впервые появляется реализация абстрактного метода Add.

в приведенном примере
FItem : TSignal;


 
Fedia   (2004-09-23 03:00) [3]

В этом примере свойство-массив основано на переменной динамического массива строк.
 
 ArUserName = array of String;

 TClassWithArray = class
 private
   function GetUserName(const MIndex: Integer): String;
   procedure AddUser(const User: String);
   procedure DeleteUser(const User: String);
 public
   UsersNames: ArUserName;
   Property UserName[const MIndex: Integer]: String read GetUserName;
 end;

implementation

function TClassWithArray.GetUserName(const MIndex: Integer): String;
begin
 if (MIndex>=0) and (MIndex<=High(UsersNames)) then
 Result:=UsersNames[MIndex] else
 Result:="Юзера с таким номером не существует";
end;

procedure TClassWithArray.AddUser(const User: String);
var
 i: integer;
begin
 i:=Length(UsersNames);
 SetLength(UsersNames, i+1);
 UsersNames[i]:=User;
end;

procedure TClassWithArray.DeleteUser(const User: String);
var
 ar: ArUserName;
 i, m: Integer;
begin
 for i:=0 to High(UsersNames) do
 if AnsiLowerCase(UsersNames[i])<>AnsiLowerCase(User) then
 begin
   m:=Length(ar);
   SetLength(ar, m+1);
   ar[m]:=UsersNames[i];
 end;
 UsersNames:=ar;
 ar:=nil;
end;


 
jack128 ©   (2004-09-23 03:27) [4]

У-у-у. Ну ты намутил :-))

uses
 contnrs;

type
 TMyClass = class(TObject);
 TMyClassList = class(TObjectList)
 protected
   function GetItem(Index: Integer): TMyClass;
   procedure SetItem(Index: Integer; AObject: TMyClass);
 public
   function Add(AObject: TMyClass): Integer;
   function Remove(AObject: TMyClass): Integer;
   function IndexOf(AObject: TMyClass): Integer;
   procedure Insert(Index: Integer; AObject: TMyClass);
   property Items[Index: Integer]: TMyClass read GetItem write SetItem; default;
 end;
Реализация каждого метода - это просто вызов унаследованного..
Наример

function TMyClassList.Add(AObject: TMyClass): Integer;
begin
 Result:= inherited Add(AObject);
end;
или
function TMyClassList.GetItem(Index: Integer): TMyClass;
begin
 Result := inherited Items[Index] as TMyClass;
end;
В принципе, если те нужно ограничить интерфейс своего списка по сравнению TObjectList (например не допускать вставки элемента) можно и так как ты. Но тогда тоже все очень просто, что то типа этого

function Add ( Item : TMyObject ) : integer;
begin
 Result := FList.Add(P);
end;

procedure Delete ( Index : integer );
begin
// P^.Free; при использовании TObjectList с OwnsObjects = True объекты при удалении сами уничтажаются..
FList.Delete(Index);
end;

Так что все очень просто.


 
Константинов ©   (2004-09-23 17:37) [5]

Громадное спасибо!
Я первый раз слышу о существовании класса TObjectList.
Буду пробовать! :)



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.47 MB
Время: 0.032 c
14-1095829330
YurikGL
2004-09-22 09:02
2004.10.10
1С и сеть


4-1093936297
Arnold
2004-08-31 11:11
2004.10.10
как по изветсному PID процесса получить список его потоков с возм


14-1095939915
zsv
2004-09-23 15:45
2004.10.10
Дисковод...


4-1094658891
Davinchi
2004-09-08 19:54
2004.10.10
Не получается отслеживать изменение буфера обмена


14-1095514391
cyborg
2004-09-18 17:33
2004.10.10
Прикольнуться чтоли над буржуями :)





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский