Delphi classes_(re)

Fri, 4 Jul 1997 16:27:32 +0200



Marius Gedminas wrote:

> In Delphi you can declare a method 'virtual' or 'dynamic' and when you want to
> override it in an descendant class, you must do it with 'override' directive.

And what happens if you don't use "override"? Does it overload the methods
then? (Does it have overloading at all?)

> I think it's only needed for Delphi compatibility, where TObject is the
> ultimate ancestor of all objects. Perhaps another compiler switch (for
> Delphi compatibility)?

I agree (see below).

Peter Gerwinski wrote:

> It's "class" = "reference to object".  Fortunately, the GCC front-end
> is able to deal with such things,

Fine! :-) (Front-end? Or back-end?)

> so we "only" have to implement the
> syntax into GPC - and take care that it doesn't break other applications
> of reference types such as `Var' parameters and procedural variables.

Yes. Are value and reference parameters of class type the same, then (in
Delphi)? Or do reference parameters pass a pointer/reference to the
reference, i.e. do they allow destroying and recreating the object?

Are pointers to classes allowed in Delphi, and what do they mean?

> We should try to be compatible to Delphi and the ANSI Object Pascal draft.

Yes. And it would be even better if there was any documentation about them
available... ;-) For Delphi, I don't have much hope since it's non-free,
but Object Pascal? (Should I do another Yahoo search...? ;-)

Larry Carter wrote:

> > > > 6. All classes to have the same ultimate ancestor object.
>
> When I actually started to think about this, I realized how this could be
> a problem.  In Delphi, this commmon object works great becuase it provides
> all the basic machinery neccessary for all objects, however, this is
> machinery that is specific to the Intel running Windows environment, the
> memory model etc.  An object of this type in GPC would probably be very
> bloated, making all its decedants bloated, becuase of all the different
> environments it would have to handle.  Perhaps a library of foundation
> objects for each OS??  Especially since this really has little to do with
> the compiler itself anyway!  :)

I think the problem we're facing is that Delphi is not really a "standalone"
language, but partly tied to one special environment. Since for gpc,
portability is a more important goal than conformance to other (non-standard)
compilers, I agree that such things do belong into libraries.

AFAICG, objects in Delphi are typically things like windows, editors, dialogs
and such "big things". Other use of OOP is for "small things" like vectors
or certain data types with their operations which are completely independent
of OS's and such.

The African Chief wrote:

> >Saves declaring those "PFoo" types, OTOH makes it impossible to declare
> >global or local objects variables (without the overhead of allocating
> >memory). If we have objects and classes, the programmer can choose what
> >(s)he prefers.
>
> Delphi also supports both Objects and Classes -

With the differences like I described them?

> so it would be nice if we could as well.

gpc will certainly not remove objects when classes are implemented. :-)

> >>    [b] the constructor does the heap allocation stuff,
> >> 	e.g., "Foo := MyFoo.Create"
> >> 		*allocates memory for Foo "(New, Foo)"
> >> 		*calls Foo^.Create (constructor)
> >
> >So it's the same as "Foo := New(MyFoo, Create)" in BP? 
> 
> More or less.

I'd like to know it exactly. Is there any difference (besides the different
syntax, of course)?

> Delphi destroys all objects that it creates itself. However,
> if you manually create an object by calling its constructor,
> you have to destroy it yourself with a call to "Free".

Sounds logical. But when does Delphi create objects by itself?
AFAIK, gpc doesn't do this yet, so we'd have to adopt this as well!?

> I suspect that Delphi sets them to Nil as well, both before
> construction and after destruction - otherwise the checks for
> "Nil" made by TObject.Free would not make any sense, since
> there is nowhere in the source code where these things are
> manually set to Nil.

So I think gpc should do this as well, at least for references (to classes).

> Probably so. However, Classes are different from "mere" objects,
> and I suspect that with Delphi, (assuming that Foo is an instance
> of a Class, and not of a mere object) if you do;
>
>    New(Foo);
>    Foo.Create;
>
> What "Foo" is pointing to may actually be undefined - and you will
> certainly get an exception when you try to do anything with "Foo".

If it's undefined in Delphi, it wouldn't hurt if there is a defined
behaviour in gpc. :-)

> In this case, it *is* necessary for Delphi compatibility. In Delphi
> all classes are descendants of TObject. Doing this in Delphi;
>
> [...]
>
> The VCL depends on this being so, and we should also
> support it (not least because Delphi programmers expect
> this to be so). This means of course that TObject then has
> to become part of the GPC RTS. For present purposes, it
> only needs to be something like this;

Sorry, but it probably can't be in the RTS, I think, because non-Delphi
programs use the same RTS, and should not have this type.

My suggestion: implement a compiler switch like '--base-class="TObject"' so
that gpc will use this class by default as a parent class if no parent is
declared (and, of course, if the current class is not "TObject" itself ;-).
With "--delphi", this switch could be set automatically. Then, TObject could
be declared in some unit (like System for Delphi). (For "completeness", we
could also have '--base-object' or so...)

BTW: This is similar to the '--uses="system"' I suggested -- things that
are not really the job of the compiler, but needed for compatibility. Such
switches seem to make the difference to the compiler as small as possible.

For BP/Delphi programs that are just recompiled with gpc, these switches
can be used. When the programs are really ported to gpc, these things would
probably put into them programs themselves, and the switches would not be
used anymore (neither for native gpc programs), I guess.

> Type TObject = Class
>    Constructor Create; virtual;
>    Destructor  Destroy; virtual;
>    Procedure Free; virtual;
> end; {I am not sure about the "virtual" bit}
>
> {and any other (private) stuff needed for any compiler
> magic that we need to do;

The only magic field in gpc would be the "VMT" link.

> Like I said, "Create" and "Destroy" are empty in TObject
> (i.e., they contain just an empty "begin end;" block).
> "Free" checks whether the pointer is Nil, and if it is not,
> it calls Destroy.

Nice little "trick", but not very systematic. "Free" is a method of an
object, and this object can be "nil^"!? Technically, it works, but "Free"
must not be virtual (I guess it isn't in Delphi)! But as a clean way, I'd
prefer a procedure... (Or should we regard it as defined behaviour to call
a static method of a non-existing object if the method doesn't access any
fields of the object?)

Larry Carter wrote:

> > Saves declaring those "PFoo" types, OTOH makes it impossible to declare
> > global or local objects variables (without the overhead of allocating
> > memory). If we have objects and classes, the programmer can choose what
> > (s)he prefers.
>
> Delphi does not allocate memory for object variables untill the object is
> actually created with its create method.

Yes, I understood this. What I meant is, you can declare BP (and gpc) objects
globally or locally (if you know the exact type at compile time), so they
will be located in the data segment or on the stack, and no memory has to be
allocated at all. (Just a minor optimization for most cases, but e.g. for
small local objects in a frequently called procedure it could make a real
difference.)

> In Delphi, the common object ancestor (TObject) provides the most basic
> methods and properties that ALL objects need (creation, destruction,
> etc.).  These are the methods/properties that are unlikely to be
> overridden (its rare that you would need a different destructor for
> example)

Sorry? I use different destructors all the time! E.g., if the object
"possesses" other objects, it has to destroy them in its destructor.

Or did you mean another destructor of another name (but that's not
overriding)?

> and having a common ancestor provides the programmer with a ready
> to go foundation for his/her objects.  I think a common ancestor is the
> right way to go.

Yes, for a library.

Ken  wrote:

>    Having the 'private' declarations visible anywhere within the unit in
> which it was defined is sort of a compatability thing with C++ 'friends'.

I had this suspicion, too. So I think, with "--borland-pascal", we should
define the visibility like in BP. For the standard gpc mode, however, we
should limit it to the class itself, and instead introduce friends like in
C++ (one of the useful features of that language, IMHO).

> Correct me if I am wrong, but a C++ class can be defined as being 'friends'
> with another class.  Since they are 'friends', they can share certain
> properties. I personaly don't care for this.  There are better ways of
> access properties in other classes!  Plus this breaks the idea of 'object
> oriented' programming and provides a way around the OO paradigm.

Well, I haven't had a need for them in my BP programs (and haven't made use
of the extended visibility in BP), but from some exercises I did in a C++
course, ISTR that they can be useful sometimes...

>    Right, only published propertied show up in the object inspector.  I
> think for now, in GPC anyway, allow 'published' and treat it as a 'public'.
> When GPC moves to X-windows or gains a visual/graphical development tool, we
> should be able to utilize it better.

Good idea. However, what is this object inspector, anyway? To me, it sounded
like a development tool, but now it seems like it's something used at
runtime, right? What do programs do with it?
-- 
Frank Heckenbach, Erlangen, Germany
heckenb@mi.uni-erlangen.de
http://www.mi.uni-erlangen.de/~heckenb/links.htm


Frank Heckenbach (heckenb@mi.uni-erlangen.de)

HTML conversion by Lluís de Yzaguirre i Maura
Institut de Lingüística Aplicada - Universitat "Pompeu Fabra"
e-mail: de_yza@upf.es