Delphi 2009부터 추가된 Generic이 있다.
간단하게 말하자면 C++의 Template라고 생각하면 되겠다.
이제 자바나 C++ 포팅할때도 충분히 쉽게 포팅할수 있게 되었다.
Generics.Collections를 보면 List 등의 클래스를 쉽게 포팅할수 있는 좋은 클래스가 많이 있다.

자바쪽 소스를 포팅하다보니 클래스에 ToArray라는 함수가 있는데 열어봐도 없길래 Generics.Collections 유닛을 열어보니 주석처리가 되어있다.
이유는 pending compiler support 라고 씌여있다.

흠... 없다면 상속해서 만들어주면 되겠군.
TObject를 담을 때 유용한 TObjectList를 상속받아서 하나 만들어보자.

type
  TMyObjectList<T: class> = class( TObjectList<T> )
  public
    function ToArray: TArray<T>;
    class procedure FreeArray( AMyArray: TArray<T> );
  end;

implementation

class procedure TMyObjectList<T>.FreeArray(AMyArray: TArray<T>);
var
  I: Integer;
begin
  for I := 0 to Length(AMyArray) - 1 do
    FreeAndNil( AMyArray[I] );

  SetLength( AMyArray, 0 );
end;

function TMyObjectList<T>.ToArray: TArray<T>;
var
  i: Integer;
begin
  SetLength(Result, Count);
  for i := 0 to Count - 1 do
    Result[i] := Items[i];
end;



type
  TMyItem = class
  public
    Data: string;
  end;

List에 담을 Item 클래스를 하나 선언하고 테스트 코드를 넣어봤다.

자동 해제 옵션을 켜고 사용할때
procedure TForm2.Button2Click(Sender: TObject);
var
  List: TMyObjectList<TMyItem>;
  Item: TMyItem;

  ItemArray: TArray<TMyItem>;
  I: Integer;
begin
  List := TMyObjectList<TMyItem>.Create;

  Item := TMyItem.Create;
  Item.Data := 'first item';
  List.Add(Item);

  Item := TMyItem.Create;
  Item.Data := 'second item';
  List.Add(Item);

  ItemArray := List.ToArray;

  for I := 0 to Length(ItemArray) - 1 do
    ShowMessage(ItemArray[I].Data);

  // 주의! 리스트가 해제될때 아이템도 같이 해제된다.
  // Free한 이후에 ItemArray는 사용이 불가하다.
  List.Free;
end;

자동 해제 옵션을 끄고 사용할때
procedure TForm2.Button1Click(Sender: TObject);
var
  List: TMyObjectList<TMyItem>;
  Item: TMyItem;

  ItemArray: TArray<TMyItem>;
  I: Integer;
begin
  List := TMyObjectList<TMyItem>.Create(False);

  Item := TMyItem.Create;
  Item.Data := 'first item';
  List.Add(Item);

  Item := TMyItem.Create;
  Item.Data := 'second item';
  List.Add(Item);

  ItemArray := List.ToArray;

  // 생성할 때 AOwnsObjects 옵션을 False로 설정했기 때문에 List를 해제하더라도 Item은 해제되지 않는다.
  List.Free;

  for I := 0 to Length(ItemArray) - 1 do
    ShowMessage(ItemArray[I].Data);

  // Array의 사용을 마치면 배열을 해제하여 Item을 해제한다.
  // 해제하기 전까지는 ItemArray를 계속 이용할 수 있다.
  TMyObjectList<TMyItem>.FreeArray( ItemArray );
end;


예전에는 TObjectList를 이용하더라도 Item을 형변환해서 사용하거나 상속받아서 새로 만들고 했었는데 Generic을 이용하니 너무나 편하다.
C++의 Template가 이제 가물가물하니 시간내서 Delphi와 비교 좀 해봐야겠다.

+ Recent posts