Delphi Lists via derivation vs via encapsulation

From: Natalie Vincent
Hi all,
As requested, here are the two ways discussed last night to implement a
TCarList. One way is via derivation, the other via encapsulation.
I favour TCarList1 because you don't need to reimplement all the other
methods on TObjectList, like Delete, Exchange, etc. The only down fall of it
is that if it is passed to something that treats it as a TObjectList, there
is the possibility that other TObject descendants could be added to the
list. You can get around this (if you're worried) overriding Notify(),
checking the type of the added object and throwing an exception if it's
incorrect. I'll leave that as an exercise to the reader! :-)
unit Unit3;
interface
uses
  Contnrs, Classes;
type
  TCar = class
  public
    function Beep: string; virtual;
  end;
  TPorche = class (TCar)
  public
    function Beep: string; override;
  end;
  TCarList1 = class (TObjectList)
  private
    function GetCar(AIndex: integer): TCar;
    procedure SetCar(AIndex: integer; const Value: TCar);
  public
    function Add(ACar: TCar): integer;
    property Items[AIndex: integer]: TCar read GetCar write SetCar; default;
  end;
  TCarList2 = class
  private
    FItems: TList;
    function GetItems(AIndex: integer): TCar;
    procedure SetItems(AIndex: integer; const Value: TCar);
  public
    constructor Create;
    destructor Destroy; override;
    function Add(ACar: TCar): integer;
    property Items[AIndex: integer]: TCar read GetItems write SetItems;
default;
  end;
implementation
{ TCarList1 }
function TCarList1.Add(ACar: TCar): integer;
begin
  result := inherited Add(ACar);
end;
function TCarList1.GetCar(AIndex: integer): TCar;
begin
  result := Get(AIndex);
end;
procedure TCarList1.SetCar(AIndex: integer; const Value: TCar);
begin
  Put(AIndex, Value);
end;
{ TCar }
function TCar.Beep: string;
begin
  result := 'Beep';
end;
{ TPorche }
function TPorche.Beep: string;
begin
  result := 'Beeeeeeeeeeeppppp';
end;
{ TCarList2 }
function TCarList2.Add(ACar: TCar): integer;
begin
  result := FItems.Add(ACar);
end;
constructor TCarList2.Create;
begin
  inherited;
  FItems := TList.Create;
end;
destructor TCarList2.Destroy;
begin
  FItems.Free;
  inherited;
end;
function TCarList2.GetItems(AIndex: integer): TCar;
begin
  result := FItems[AIndex];
end;
procedure TCarList2.SetItems(AIndex: integer; const Value: TCar);
begin
  FItems[AIndex] := Value;
end;
end.
============================
Natalie Vincent
Developer
Footy Tipping Software
============================
mailto:natalie@footy.com.au 
http://www.footy.com.au/nat/ 
============================