StartprogrammingusingObjectPascal:NewsApplicationInObjectOriented
객체지향 파스칼에서의 뉴스 프로그램
이 예제에서는 객체지향 기법을 사용하여 뉴스 프로그램을 재작성하려고 합니다. 또한 뉴스를 여러 개의 파일로 분류해야 합니다.
새로운 GUI 프로그램을 만들었고 oonews라고 이름 지었습니다.
다음 예제는 뉴스 기능이 있는 TNews 클래스가 들어있는 새 유닛입니다.
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.
메인 폼에 다음과 같이 편집 상자, 콤보상자, 세 개의 단추, 메모, '두 개의 레이블 구성요소를 추가했습니다.
메인 유닛에는 이 코드를 작성합니다.
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;