2012년 10월 18일 목요일

제네릭 이해를 돕기 위한 간단한 사용(TList)


우선 얼마전에  MyRecord 를 TList에 구겨 넣었던 것을 기억하실 것입니다.
그때 선언 방법과 비교해 보세요..
  TMyClass = class
    no: integer;
    fname: string;
    lname: string;
    phone: string;
    addr: string;
  private
    function GetName: string;
  public
    property name: string read GetName;
    constructor create(ino:integer; ifname,ilname,iphone,iaddr: string);
  end;
OOP는 여기에서 처럼 name을 얻을 수 있다는 것이 묘미가 아닐까요.
데이터와 메소드를 갖이 가지고 있으니까요?

1. 우선 객체(인스턴스)를 선언 하여야 겠지요.
  private
    MyList: TList<TMyClass>;
이게 제네릭문법입니다. TList<T>라는 클라스는 델파이가 만들어 놓았고, 어떠한 타입(형식)의 자료도 처리 할 수 있게 하여 주었습니다.

2. 폼 생성시 인스턴스를 만들고 폼이 닫일때 날려주어야 겠지요.
procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
var
  idx: TMyClass;
begin
  for idx in MyList do begin
    idx.Free;
  end;
  MyList.Free;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  MyList:= TList<TMyClass>.Create;
end;

3. 자료를 TList에 넣습니다.
procedure TForm3.Button1Click(Sender: TObject);
var
  idx: Integer;
  iStrings: Tstrings;
begin
  iStrings:= TstringList.Create;
  try
    for idx := 0 to StrHolder1.Strings.count - 1 do begin
        iStrings.CommaText:= StrHolder1.Strings[idx];
        if istrings.Count < 5 then continue;
        MyList.Add(TMyClass.create( StrToInt(iStrings[0]), iStrings[1], iStrings[2], iStrings[3], iStrings[4]));
    end;
  finally
    iStrings.Free;
  end;
end

여기에 StrHolder 라는 RXLIB 컴포넌트를 사용하였는데 설치해 두변 편리 할 것입니다.
기본 컴포넌트 이외에 많이 설치하는 컴포넌트일 것입니다. 없으면 LIstBox를 폼에 올려 놓고 사용해서 되며, 파싱은 commaText 메소드를 이용합니다. 데이터는
  1,이,정귀,515-5513,광주광역시 이런 형태로 만들어져 있습니다.

4. 넣어진 자료가 정상으로 잘 들어 갔는지 확인하기 위하여
procedure TForm3.Button2Click(Sender: TObject);
var
  idx: TMyClass;
begin
  ListBox2.Items.Clear;
  for idx in MyList do
  begin
    listbox2.Items.Add(idx.GetName)
  end;
end;

5. 당연히
function TMyClass.GetName: string;
begin
  result:= fname + lname;
end;
도 있어야 겠지요...

6. 소팅을 해보겠습니다.
procedure TForm3.Button3Click(Sender: TObject);
begin
  MyList.Sort(TComparer<TMyClass>.Construct(
    function(const Item1, Item2: TMyClass): integer
    begin
      result := CompareText(Item1.fname, Item2.fname); // 다른 내용으로 해도 되겠지요
    end));
end;

7. 당연히 Uses 절에 Generics.defaults, Generics.collections 을 추가합니다.
8. XE2 부턴 가는 Record 에서도 메소드를 포함 할 수 있습니다. Class 와 Record는 계승의 차이만 있나?

type
  {
  pMyRecord = ^MyRecord;
  MyRecord = record
    no: integer;
    fname: string;
    lname: string;
    phone: string;
    addr: string;
    function GetName:string;
  end;
  }

9. GetName 을 구현하고...

function TMyRecord.GetName: string;
begin
  Result:= FName + ' ' + LName;
end;


10. 리스트에 데이터 저장시
procedure TForm3.Button1Click(Sender: TObject);
var
  idx: integer;
  iStrings: Tstrings;
  iRecord: TMyRecord;
begin
  iStrings := TstringList.create;
  try
    for idx := 0 to StrHolder1.Strings.count - 1 do begin
      iStrings.CommaText := StrHolder1.Strings[idx];
      if iStrings.count < 5 then continue;
      New(iRecord);
      iRecord.no:= StrToInt(iStrings[0]);
      iRecord.fname:= iStrings[1];
      iRecord.lname:= iStrings[2];
      iRecord.phone:= iStrings[3];
      iRecord.addr:= iStrings[4];
      iList.Add(iRecord);
    end;
  finally
    iStrings.free;
  end;
end;

11. 내용 확인은 
procedure TForm3.Button2Click(Sender: TObject);
var
  idx: TMyRecord;
begin
  for idx in iList do
    ListBox1.Items.Add(idx.GetName);
end;
하면 됩니다.

댓글 없음:

델파이 12.1이냐 11.3이냐?

 델파이가 12.1이 나왔습니다. 혹시 11.3버전의 커뮤니티버전이 필요하시는분이 있을 수 있을 것 같아 https://altd.embarcadero.com/.../RADStudio_11_3_esd_28... 와 이것 찾느랴 엄청고생함.