home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / handson / archive / Issue155 / delphi / BookObs / books.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1999-05-19  |  9.8 KB  |  337 lines

  1. unit books;
  2. { PC Plus sample Delphi program.
  3.   Illustrates the basic techniques for declaring a class and
  4.   constructing and destroying objects.
  5.   Also shows how to create a simple object hierarchy.
  6. }
  7.  
  8. interface
  9.  
  10. uses
  11.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  12.   Forms, Dialogs, StdCtrls;
  13.  
  14.  
  15. type
  16.   TForm1 = class(TForm)
  17.     ListBox1: TListBox;
  18.     BookEd: TEdit;
  19.     AuthorEd: TEdit;
  20.     Label1: TLabel;
  21.     Label2: TLabel;
  22.     AddBtn: TButton;
  23.     ClearBtn: TButton;
  24.     ExitBtn: TButton;
  25.     ShowBtn: TButton;
  26.     ComboBox1: TComboBox;
  27.     ExtraLabel: TLabel;
  28.     ExtraEdit: TEdit;
  29.     GoreScoreCombo: TComboBox;
  30.     procedure ExitBtnClick(Sender: TObject);
  31.     procedure FormCreate(Sender: TObject);
  32.     procedure FormClose(Sender: TObject; var Action: TCloseAction);
  33.     procedure AddBtnClick(Sender: TObject);
  34.     procedure ShowBtnClick(Sender: TObject);
  35.     procedure ClearBtnClick(Sender: TObject);
  36.     procedure ComboBox1Change(Sender: TObject);
  37.   private
  38.     { Private declarations }
  39.   public
  40.     { --- My declarations --- }
  41.     procedure AddBookOb;
  42.     procedure AddHorrorBookOb;
  43.     procedure AddRefBookOb;
  44.     procedure ShowObList;
  45.     procedure FreeObs;
  46.   end;
  47.  
  48. { declare a fixed-length string                 }
  49.   bkstr = string[70];
  50. { declare a gorerating for HorrorBookOb         }
  51.   gorerating = 0..10;
  52.  
  53. { declare a BookOb class        }
  54.   BookOb = class(TObject)
  55.     name   : bkstr;
  56.     author : bkstr;
  57.     function Describe : bkstr;  virtual; {!!! This is the VIRTUAL method !!!}
  58.     constructor Create( aName, anAuthor : bkstr );
  59.     destructor Destroy; override; { remember to override the destructor! }
  60.   end;
  61.  
  62. { declare a HorrorBookOb class }
  63.   HorrorBookOb = class(BookOb)
  64.     gorescore : integer;
  65.     function Describe : bkstr; override; {!!! Here it's overridden }
  66.     constructor Create( aName, anAuthor : bkstr; aGorescore : gorerating );
  67.     destructor Destroy; override;
  68.   end;
  69.  
  70. { declare a RefBookOb class }
  71.   RefBookOb = class(BookOb)
  72.     reftype : bkstr;
  73.     function Describe : bkstr; override; {!!! Here it's overridden }
  74.     constructor Create( aName, anAuthor, aReftype : bkstr);
  75.     destructor Destroy; override;
  76.   end;
  77.  
  78. var
  79.   Form1: TForm1;
  80.   ObList : TList; { declare a TList to hold our objects }
  81.  
  82. implementation
  83.  
  84. {$R *.DFM}
  85.  
  86.  
  87. procedure TForm1.ShowObList;
  88. { Show each ob's ID (its name and author) in the ListBox }
  89. { also show extra data for HorrorBookObs and RefBookObs  }
  90. var
  91.    i :integer;
  92. begin
  93. {  ListBox1.Clear; }
  94.   if ObList.Count = 0 then
  95.     ListBox1.Items.Add( 'No books in the list!' )
  96.   else
  97.   for i := 0 to ObList.Count - 1 do
  98.       ListBox1.Items.Add( BookOb(ObList.Items[i]).Describe );
  99. end;
  100.  
  101. procedure TForm1.FreeObs;
  102. { Free the objects in the ObList.
  103.   ------------------------------
  104.   This first frees all the objects in the ObList.
  105.   Then is Clears the ObList.
  106.   You must do both. If you Clear the ObList but don't Free the
  107.   individual objects, they will hang around uselessly in memory.
  108.   If you Free the objects but don't clear the ObList, the ObList
  109.   will still 'think' it contains valid objects (which it doesn't,
  110.   since they've been freed) }
  111. var
  112.   i : integer;
  113. begin
  114.   for i := 0 to ObList.Count - 1 do
  115.       if ObList.Items[i] <> nil then
  116.       begin
  117.          ListBox1.Items.Add( 'Call to FREE Ob: ' +
  118.                              BookOb(ObList.Items[i]).Describe );
  119.          BookOb(ObList.Items[i]).Free;
  120.       end;
  121.   ObList.Clear;
  122. end;
  123.  
  124. procedure TForm1.ExitBtnClick(Sender: TObject);
  125. begin
  126.   Close;
  127. end;
  128.  
  129. procedure TForm1.FormCreate(Sender: TObject);
  130. begin
  131.   { Create a TList called ObList when the main form is created }
  132.   ObList := TList.Create;
  133. end;
  134.  
  135. procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
  136. begin
  137.   FreeObs;     { Free the objects in the ObList, then...      }
  138.   ObList.Free; { Free the ObList when the main form is closed }
  139. end;
  140.  
  141. procedure TForm1.AddBookOb;
  142. { add an ordinary BookOb to the ObList and display its data on the List box }
  143. var
  144.   book : BookOb;
  145. begin
  146.   book := BookOb.Create( BookEd.Text, AuthorEd.Text );
  147.   ObList.Add( book );
  148. end;
  149.  
  150. procedure TForm1.AddRefBookOb;
  151. { add a RefBookOb to the ObList and display its data on the List box        }
  152. var
  153.   book : RefBookOb;
  154. begin
  155.   if (ExtraEdit.Text = '') then
  156.         MessageDlg('You must enter a book type (e.g. "Physics" or "Art") ',
  157.                     mtInformation, [mbOk], 0)
  158.   else
  159.   begin
  160.     book := RefBookOb.Create( BookEd.Text, AuthorEd.Text, ExtraEdit.Text );
  161.     ObList.Add( book );
  162.   end;
  163. end;
  164.  
  165. procedure TForm1.AddHorrorBookOb;
  166. { add a HorrorBookOb to the ObList and display its data on the List box     }
  167. var
  168.   book  : HorrorBookOb;
  169.   score : integer;
  170.   ok    : boolean;
  171. begin
  172.   ok := true;
  173.   { First check that a valid gorescore has been entered                     }
  174.   { try to convert the contents o ExtraEdit to an integer                   }
  175.   try
  176.     score := StrToInt(GoreScoreCombo.Text);
  177.   except
  178.      on EConvertError do     { Error if user did not enter an integer }
  179.      begin                   { recover from this by setting score to  }
  180.        score := 0;           { 0 and displaying a message             }
  181.        MessageDlg('Invalid gorescore entry!', mtInformation,[mbOk], 0);
  182.       ok := false;
  183.      end;
  184.   end;
  185.   if ok then                { if the integer is valid, is it 0..10?  }
  186.      if (score < 0) or (score > 10) then
  187.         MessageDlg('The score must be a number from 0 to 10!', mtInformation,
  188.                    [mbOk], 0)
  189.   else
  190.   begin                     { if all is ok, create the object       }
  191.     book := HorrorBookOb.Create( BookEd.Text, AuthorEd.Text, score );
  192.     ObList.Add( book );
  193.   end;
  194. end;
  195.  
  196. procedure TForm1.AddBtnClick(Sender: TObject);
  197. { User wants to add a book object. Determine the type of object         }
  198. { by the Combo box item that's been selected, then call an appropriate  }
  199. { method.                                                               }
  200. begin
  201.   if ((BookEd.Text = '') or (AuthorEd.Text = '')) then
  202.         MessageDlg('You must enter a book and an author!', mtInformation,
  203.       [mbOk], 0)
  204.   else
  205.   if ComboBox1.Text = 'Horror' then
  206.     AddHorrorBookOb
  207.   else
  208.   if ComboBox1.Text = 'Reference' then
  209.     AddRefBookOb
  210.   else
  211.     AddBookOb;
  212. end;
  213.  
  214. procedure TForm1.ShowBtnClick(Sender: TObject);
  215. begin
  216.   ShowObList;
  217. end;
  218.  
  219. procedure TForm1.ClearBtnClick(Sender: TObject);
  220. begin
  221.   FreeObs;
  222. end;
  223.  
  224.  
  225. procedure TForm1.ComboBox1Change(Sender: TObject);
  226. { When a change (normally a selection) is made in the ComboBox, see if the    }
  227. { selected item indicates a special type of book. If so, display a label      }
  228. { and text entry field to allow the user to enter the additional data needed  }
  229. { to create an object of the specified type.                                  }
  230. begin
  231.   if ComboBox1.Text = 'Horror' then
  232.   begin
  233.     ExtraLabel.Caption := 'Enter Gore score [1 to 10]';
  234.     ExtraLabel.Show;
  235.     ExtraEdit.Hide;
  236.     GoreScoreCombo.Show;
  237.     GoreScoreCombo.SetFocus;
  238.   end
  239.   else if ComboBox1.Text = 'Reference' then
  240.   begin
  241.     ExtraLabel.Caption := 'Enter the type of reference book';
  242.     ExtraEdit.Text := 'General';
  243.     ExtraLabel.Show;
  244.     ExtraEdit.Show;
  245.     GoreScoreCombo.Hide;
  246.     ExtraEdit.SetFocus;
  247.   end
  248.   else
  249.   begin   { if it's an ordinary book, don't display the extra edit box       }
  250.     ExtraLabel.Hide;
  251.     ExtraEdit.Hide;
  252.     GoreScoreCombo.Hide;
  253.   end;
  254. end;
  255.  
  256.  
  257. { --- BOOKOB METHOD --- }
  258. function BookOb.Describe : bkstr;
  259. { Concatenate name and author - an illustrative, rather than a useful method! }
  260. begin
  261.   result := Format( '[General Book] %s by %s', [name,author]);
  262. end;
  263.  
  264. { --- CONSTRUCTORS --- }
  265. { Create each object by calling its ancestor's constructor:
  266.        inherited Create;
  267.   then initialising any additional fields }
  268.  
  269. constructor BookOb.Create( aName, anAuthor : bkstr );
  270. { a standard BookOb. Call default initialisation, then init the 2 fields }
  271. begin
  272.   inherited Create;
  273.   Form1.ListBox1.Items.Add( 'CONSTRUCTOR: BookOb.Create' );
  274.   name := aName;
  275.   author := anAuthor;
  276. end;
  277.  
  278. function HorrorBookOb.Describe : bkstr;
  279. { Concatenate name and author - an illustrative, rather than a useful method! }
  280. begin
  281.   result := Format( '[Horror Book] %s by %s. Gore Score: %d',
  282.                     [name,author,gorescore]);
  283. end;
  284.  
  285. constructor HorrorBookOb.Create( aName, anAuthor : bkstr; aGorescore : gorerating );
  286. { a HorrorBookOb. Call its ancestor (BookOb) constructor, then init gorescore }
  287. begin
  288.   inherited Create(aName, anAuthor);
  289.   Form1.ListBox1.Items.Add( 'CONSTRUCTOR: HorrorBookOb.Create' );
  290.   gorescore := aGorescore;
  291. end;
  292.  
  293. function RefBookOb.Describe : bkstr;
  294. { Concatenate name and author - an illustrative, rather than a useful method! }
  295. begin
  296. result := Format( '[Reference Book] %s by %s. Book type: %s',
  297.                     [name,author,reftype]);
  298. end;
  299.  
  300. constructor RefBookOb.Create( aName, anAuthor, aReftype : bkstr );
  301. { a RefBookOb. Call its ancestor (BookOb) constructor, then init reftype      }
  302. begin
  303.   inherited Create(aName, anAuthor);
  304.   Form1.ListBox1.Items.Add( 'CONSTRUCTOR: RefBookOb.Create' );
  305.   reftype := aReftype;
  306. end;
  307.  
  308. { --- DESTRUCTORS --- }
  309. { Destroy the objects you created when you've finished with them.
  310.   If these objects contain references to other objects or resources, the
  311.   destructor should first Free these. It should then call the inherited
  312.   destructor }
  313. destructor BookOb.Destroy;
  314. begin
  315.   Form1.ListBox1.Items.Add( 'DESTRUCTOR: BookOb.Destroy' );
  316.   name := '';
  317.   author := '';
  318.   inherited Destroy;
  319. end;
  320.  
  321. destructor HorrorBookOb.Destroy;
  322. begin
  323.   Form1.ListBox1.Items.Add( 'DESTRUCTOR: HorrorBookOb.Destroy' );
  324.   gorescore := 0;
  325.   inherited Destroy;
  326. end;
  327.  
  328. destructor RefBookOb.Destroy;
  329. begin
  330.   Form1.ListBox1.Items.Add( 'DESTRUCTOR: RefBookOb.Destroy' );
  331.   reftype := '';
  332.   inherited Destroy;
  333. end;
  334.  
  335.  
  336. end.
  337.