StartprogrammingusingObjectPascal:NewsApplicationInObjectOriented

From 흡혈양파의 번역工房
Jump to: navigation, search

객체지향 파스칼에서의 뉴스 프로그램

이 예제에서는 객체지향 기법을 사용하여 뉴스 프로그램을 재작성하고자 합니다. 또한 뉴스를 여러 개의 파일로 분류해야 합니다.

새로운 GUI 프로그램을 만들었고 oonews라고 이름 지었습니다.

다음 예제는 뉴스 기능이 있는 TNews 클래스가 들어있는 새 Unit입니다.

unit news;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

type
    TNewsRec = record
        ATime: TDateTime;
        Title: string[100];
    end;

    { TNews }

    TNews = class
    private
        F: file of TNewsRec;
        fFileName: string;
    public
        constructor Create(FileName: string);
        destructor Destroy; override;
        procedure Add(ATitle: string);
        procedure ReadAll(var NewsList: TStringList);
        function Find(Keyword: string;
            var ResultList: TStringList): Boolean;
    end;

implementation

{ TNews }

constructor TNews.Create(FileName: string);
begin
    fFileName:= FileName;
end;

destructor TNews.Destroy;
begin
    inherited Destroy;
end;

procedure TNews.Add(ATitle: string);
var
    Rec: TnewsRec;

begin
    AssignFile(F, fFileName);
    if FileExists(fFileName) then
    begin
        FileMode:= 2; // Read/write access
        Reset(F);
        Seek(F, FileSize(F));
    end

    else
        Rewrite(F);
    Rec.ATime:= Now;
    Rec.Title:= ATitle;
    Write(F, Rec);
    CloseFile(F);
end;

procedure TNews.ReadAll(var NewsList: TStringList);
var
    Rec: TnewsRec;

begin
    NewsList.Clear;
    AssignFile(F, fFileName);
    if FileExists(fFileName) then
    begin
        Reset(F);
        while not Eof(F) do
        begin
            Read(F, Rec);
            NewsList.Add(DateTimeToStr(Rec.ATime) + ' : ' + Rec.Title);
        end;
        CloseFile(F);
    end;
end;

function TNews.Find(Keyword: string; var ResultList: TStringList): Boolean;
var
    Rec: TnewsRec;

begin
    ResultList.Clear;
    Result:= False;
    AssignFile(F, fFileName);
    if FileExists(fFileName) then
    begin
        Reset(F);
        while not Eof(F) do
        begin
            Read(F, Rec);
            if Pos(LowerCase(Keyword), LowerCase(Rec.Title)) > 0 then
            begin
                ResultList.Add(DateTimeToStr(Rec.ATime) + ' : ' + Rec.Title);
                Result:= True;
            end;
        end;
        CloseFile(F);
    end;
end;

end.

메인 폼에 다음과 같이 편집 상자, 콤보상자, 세 개의 버튼, 메모, '두 개의 레이블 구성요소를 추가했습니다.

Lazarus 11.png

메인 유닛에는 이 코드를 작성합니다.

unit main;

{$mode objfpc}{$H+}

interface

uses
    Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics,
        Dialogs, News, StdCtrls;

type

    { TForm1 }

    TForm1 = class(TForm)
        btAdd: TButton;
        btShowAll: TButton;
        btSearch: TButton;
        cbType: TComboBox;
        edTitle: TEdit;
        Label1: TLabel;
        Label2: TLabel;
        Memo1: TMemo;
        procedure btAddClick(Sender: TObject);
        procedure btSearchClick(Sender: TObject);
        procedure btShowAllClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
    private
        { private declarations }
    public
        NewsObj: array of TNews;
        { public declarations }
end;

var
    Form1: TForm1;

implementation

{ TForm1 }


procedure TForm1.FormCreate(Sender: TObject);
var
    i: Integer;
begin
    SetLength(NewsObj, cbType.Items.Count);
    for i:= 0 to High(NewsObj) do
        NewsObj[i]:= TNews.Create(cbType.Items[i] + '.news');
end;

procedure TForm1.btAddClick(Sender: TObject);
begin
    NewsObj[cbType.ItemIndex].Add(edTitle.Text);
end;

procedure TForm1.btSearchClick(Sender: TObject);
var
    SearchStr: string;
    ResultList: TstringList;
begin
    ResultList:= TStringList.Create;
    if InputQuery('Search News', 'Please input keyword', SearchStr) then
        if NewsObj[cbType.ItemIndex].Find(SearchStr, ResultList) then
        begin
            Memo1.Lines.Clear;
            Memo1.Lines.Add(cbType.Text + ' News');
            Memo1.Lines.Add('--------------------------------------------------');
            Memo1.Lines.Add(ResultList.Text);
        end
    else
        Memo1.Lines.Text:= SearchStr + ' not found in ' +
            cbType.Text + ' news';
    ResultList.Free;
end;

procedure TForm1.btShowAllClick(Sender: TObject);
var
    List: TStringList;
begin
    List:= TStringList.Create;
    NewsObj[cbType.ItemIndex].ReadAll(List);
    Memo1.Lines.Clear;
    Memo1.Lines.Add(cbType.Text + ' News');
    Memo1.Lines.Add('-----------------------------------------------------------');
    Memo1.Lines.Add(List.Text);
    List.Free;
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
    i: Integer;
begin
    for i:= 0 to High(NewsObj) do
        NewsObj[i].Free;
    NewsObj:= nil;
end;

initialization
    {$I main.lrs}

end.

앞의 예제에서 다음 사실들을 살펴보겠습니다.

1. 사용 여부에 따라 할당하고, 확장하고, 축소하고, 없앨 수 있는 동적 배열을 사용했습니다. news 객체의 동적 배열을 다음과 같이 선언했습니다.

   NewsObj: array of TNews;

실행 시간동안 사용하기 전에, SetLength 프로시저를 사용하여 초기화 하는 것이 좋습니다.

   SetLength(NewsObj, 10);

이는 배열에 10개 요소를 할당한다는 의미입니다. 이는 일반 배열의 선언과 유사합니다.

   NewsObj: array [0 .. 9] of TNews;

일반적인 배열의 크기는 프로그램이 실행하는 동안 항상 정해진 그대로 남아있지만, 동적 배열의 크기는 늘였다 줄였다 할 수 있습니다.

이 예제에서는 콤보 상자에 존재하는 분류에 따라 배열을 초기화합니다.
   SetLength(NewsObj, cbType.Items.Count);
ComboBox.Items에 더 많은 분류를 추가하면, 동적 배열의 크기는 이에 따라 증가할 것입니다.

2. TNews 형식은 클래스이며, 이것을 바로 사용할 수 없습니다. NewsObj와 같이 클래스의 객체 인스턴스를 선언해야 합니다.

3. 프로그램의 마지막에는 객체를 릴리스 하고, 그 다음 동적 배열을 릴리스 했습니다.

   for i:= 0 to High(NewsObj) do
      NewsObj[i].Free;
   NewsObj:= nil;