Текущий архив: 2004.10.10;
Скачать: CL | DM;
Вниз
Подскажите, как правильно работать со свойствами-массивами Найти похожие ветки
← →
Константинов © (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;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.024 c