[fpc-pascal]Polymorphism of class field

Full_Name memsom at post.interalpha.co.uk
Thu Aug 30 11:10:31 CEST 2001


Quoting Michael Van Canneyt <michael.vancanneyt at wisa.be>:


> You can't. 

Although it might get messy, surely he could defire a variant record? Something 
like:

type
  TStackElemType = (stNull, stString, stReal);

  TStackElem = record
    ElemType: TStackElemType;
    case tag: integer of
      0: (RealResult: Real);
      1: (StringResult: String[255]);
  end;

  PStackelem = ^TStackElem;

  procedure setStringElemData(st: string); //sets Elemtype to 'stReal'
  procedure setRealElemData(re: real); //sets Elemtype to 'stString'
  procedure CrearElem; //sets Elemtype to 'stNull'

But, to be honest, if you go that far you may as well use classes.

A more elegant solution is to go the Smalltalk route, and create classes that 
descend from a single ancestor. But that's not actually all that easy or 
gracefull in Pascal.

I think a more worrying thing is your following class:

> > type
> >
> >          TStackElem = class
> >                  public
> >                  constructor Init; virtual;
> >                  destructor Done; virtual;
> >                  Prolog : TRPLObjectType;
> >                  Next : TStackElem;
> >                  function Decomp : string; virtual; abstract;
> >          end;

This class will never call 'Done'. Not in the Delphi sense of the word. Try the 
following:

destructor TStackElem.Done;
begin
  //whatever you already did

  writeln('hello, I have destroyed myself');

  //whatever you already did
end;

You will never see the line 'hello, I have destroyed myself' unless you 
explicitly call 'done' and that is wrong. What you should actually do (and this 
is in the standard btw, it's not just me being pedantic) is call 'free'. 
Because Delphi has a policy of only having a single destructor, and this 
through polymorphism should be called 'destroy' and should be 'overridden' you 
are *never* freeing your resources. You may as well change the Destructors name 
to 'HelloIamAMemoryLeak'.

Before anyone jumps on me, this is tested under FPC 1.02 *and* FPC 1.04, 
compiled with '-S2'. The destructor never gets called if you call 'free'. It 
would be *really* nice if you could write this into the docs for 1.2, I expect 
it's already there, but it's obviously not evident coz people keep making this 
mistake. If you're going to allow people to use Delphi stle classes, they 
should always inherit from TObject (even if the user doesn't specify this) and 
therefore the destructor has to be called Destroy. 

Breaking this is really bad, unless calling 'done' directly does 
call 'destroy'. I note however that if I create a class with 2 destructors, 
firstly FPC1.04 complains that I do have 2, and secondly only 'done' gets 
called if I call 'done' and only 'destroy' gets called if I call 'free'. 

Sorry to moan again, but this is something that will cause many people problems 
if it's not addressed. The simplest, cheapest and less painfull would be 
to 'warn' people if they are using 'class' style constructs and 
their 'destructor' is not called 'destroy'.

Matt

--

"Computer games don't affect kids; I mean if Pac-Man affected us as kids, 
we'd all be running around in darkened rooms, munching magic pills and 
listening to repetitive electronic music." 
Kristian Wilson, 
Nintendo, Inc, 1989

-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s+++:+ a- C++ UL+ P L++ E---- W- N+ o+ K- w 
O- M V PS PE-- Y PGP- t- 5-- X- R- tv+ b+ DI++ D+ 
G e++ h--- r+++ y+++ 
------END GEEK CODE BLOCK------




More information about the fpc-pascal mailing list