Board index » delphi » OOP problem with object types, inheritance and association between objects

OOP problem with object types, inheritance and association between objects

Hi all you Pascal programmers!

I'm working on a huge OOP tool. I wonder how
you create a method that returns TRUE if the object
is inherited out of another object, ie. it is associated
to another object.

I would like it to be something like;

function IsAssociation (What : ObjectType) : boolean;

I've been trying lot's of things with VMT access and
VMT links low-low-low-level things. But there must
be a way of doing it!!!

Any suggestions or hints?

Greetings, Johan

PS. Please send a message to my personal mail box as well as to
the news group when answering. It's j...@ts.umu.se.

 

Re:OOP problem with object types, inheritance and association between objects


Quote
Johan Larsson <j...@ts.umu.se> writes:
> Hi all you Pascal programmers!

> I'm working on a huge OOP tool. I wonder how
> you create a method that returns TRUE if the object
> is inherited out of another object, ie. it is associated
> to another object.

I suppose, you mean class instead of object. (Inheritance is between classes,
not objects.)

Quote
> I would like it to be something like;

> function IsAssociation (What : ObjectType) : boolean;

I guess you need two parameters here, or would this be a method?

Quote
> I've been trying lot's of things with VMT access and
> VMT links low-low-low-level things. But there must
> be a way of doing it!!!

I needed this myself several times... I fear it's impossible. :-( One of the
many weaknesses of TP's object concept - besides the "strange" scoping
("Private"), that I'd rather call a bug, and other things...
(Btw, does Delphi address this problem - anyone knows?)

I could think of a solution requiring registering each class with its parent
(I guess you know how to do that), but that's quite inconvenient...
If you require registering because of streams or so, this might not be too
much more overhead - but still unhandsome...

Hope this helps,
Frank

Re:OOP problem with object types, inheritance and association between objects


Quote
> > I'm working on a huge OOP tool. I wonder how
> > you create a method that returns TRUE if the object
> > is inherited out of another object, ie. it is associated
> > to another object.
> I suppose, you mean class instead of object. (Inheritance is between cl=
asses,
> not objects.)

Mmm. But I thought the distinction in Pascal is between object types and
object instances,
or just "objects" (both). In C, i thought the terms class and instance
was used. Are
you sure?

Quote
> > I would like it to be something like;
> > function IsAssociation (What : ObjectType) : boolean;
> I guess you need two parameters here, or would this be a method?

It's a method, implemented in the parent object for all other objects
(classes...).

Quote
> > I've been trying lot's of things with VMT access and
> > VMT links low-low-low-level things. But there must
> > be a way of doing it!!!
> I needed this myself several times... I fear it's impossible. :-( One o=
f the
> many weaknesses of TP's object concept - besides the "strange" scoping
> ("Private"), that I'd rather call a bug, and other things...
> (Btw, does Delphi address this problem - anyone knows?)

Private fields isn't very spooky. The scope thing works as follows;
pivate fields are
accessable in the current unit, but not outside it. It must be this way
if Borland don't
use some "friend"-C-thing.

Quote
> I could think of a solution requiring registering each class with its p=
arent
> (I guess you know how to do that), but that's quite inconvenient...
> If you require registering because of streams or so, this might not be =
too
> much more overhead - but still unhandsome...

Yes, I've seen that solution in some programs. But, as you say, it's a
bit ugly
and I am a bit pedantic about these things. But, when a method inside
a object calls it's parent object by the following code;

        Inherited SomeMethodFromParent;

The object must know the address of the parent method. Therefor, the
parent
must internally be known for Borland Pascal. The question is; how is it
known?
What is the link between the parent VMT and the object's VMT? =

All these VMT things is a bit fuzzy. I've tried the following approach
to
the "find parent" dilemma;

    1. Go to the VMT start address
    2. Walk forward passed the two size fields (negsize and size)
    3. Compare objects VMT method links (pointers) until a NIL pointer
is
       found (must be done since I don't know where the VMT ends).
    4. If at least one link was equal, the objects is associated in some
way.

This is very primitive, since it not works always (at least one virtual
method
must not be overridden by the child obj.), and also allows _any_
association.
It would be better with strict association, ie. TRUE only if objects are
directly
inherited out of each other.

/J

PS. Please forward answers to my mail address; j...@ts.umu.se. Also
check out
    EFLIB at http://www.ts.umu.se/~jola/EFLIB/. It's free and alomst 1
MB srce.
_______________________________________________________________________
Johan Larsson            Telefon (hem)
Istidsgatan 33, 2 tr.    090-199060
906 55 Ume=E5              j...@ts.umu.se      http://www.ts.umu.se/~jola=

Re:OOP problem with object types, inheritance and association between objects


Quote
Johan Larsson wrote:
> But, when a method inside
> a object calls it's parent object by the following code;

>         Inherited SomeMethodFromParent;

> The object must know the address of the parent method. Therefor, the
> parent must internally be known for Borland Pascal.

In BP6.0 there was no reserved word inherited, you just called directly:

          TParent.SomeMethod;

and I afraid TP7.0 simply finds parent during the compilation time when
meets call of inherited method.

--
Viatcheslav   <neste...@em.uni-frankfurt,de>
-------Knowledge is power. R.Bacon----------

Re:OOP problem with object types, inheritance and association between objects


Quote
>   function IsAssociation(what: ObjectType): Boolean;
>   begin
>    IsAssociation := (TypeOf(Self)=TypeOf(what)) OR
>      inherited_object.IsAssociation(what)
>   end;
> Let me know if this works (or even better, if you find a better way...)

Your idea is very interesting. But it doesn't seem to work. Predend
that you've got a object hierarchy like

      a --- b
         |
         +-- c - d

If you call IsAssociation in b with d as a parameter, it won't
return TRUE, because objects are nested. But if one extrapolate
your idea slightly one could make a method like;

procedure a.IsAssociation (What : ObjectPointerType) : boolean;
begin
    What := (TypeOf(Self) = TypeOf(What^)) or
            Inherited IsAssociation (What) or
            (What^.IsInitialized and What^.IsAssociation(@Self));
end;

But this I believe will not work either, beacuse it's endless
recursion (how do you know when to stop checking the called object).
Also I am sceptical to the TypeOf operator. Are you really sure
that TypeOf returns TRUE when used with Inherited. Isn't the type of
"self" equal when compared in "IsAssociation" and "Inherited
IsAssociation"? Self should always be of the same type?!

But I don't think it's impossible to do this association thing.
If you compare VMTs and uses a modified IsAssociation, it
could would should work. :-/

/J

Re:OOP problem with object types, inheritance and association between objects


In a message that I haven't seen, someone wrote:

Quote
> I'm working on a huge OOP tool. I wonder how
> you create a method that returns TRUE if the object
> is inherited out of another object, ie. it is associated
> to another object.

> I would like it to be something like;
> function IsAssociation (What : ObjectType) : boolean;

In Delphi, of course, you'd just use "is". If you're using BP7 or TPW, you can
use "dynamic" methods. It's a bit clunky, but each class that has at least one
dynamic method will have its own DMT. Each DMT contains a pointer to an
ancestral DMT. So, all you'd have to do is compare DMT pointers; if they don't
match, you'd walk the chain until they do match or until you reach a Nil
ancestral pointer.

VMT/DMT formats are well documented in the Inside Borland Pascal chapter.

--

http://www.midnightbeach.com/jon   Personal Pages
http://www.midnightbeach.com/jon/pubs Programming Publications
http://www.midnightbeach.com/hs             Home School Resource List

Re:OOP problem with object types, inheritance and association between objects


Quote
Johan Larsson <j...@ts.umu.se> writes:
> > > I'm working on a huge OOP tool. I wonder how
> > > you create a method that returns TRUE if the object
> > > is inherited out of another object, ie. it is associated
> > > to another object.

> > I suppose, you mean class instead of object. (Inheritance is between cl=
> asses,
> > not objects.)

> Mmm. But I thought the distinction in Pascal is between object types and
> object instances,
> or just "objects" (both). In C, i thought the terms class and instance
> was used. Are
> you sure?

OK, "class" is C++ terminology, I admit. I still prefer "class" to "type", in
order to distinguish from non-object types.

However, I haven't heard "object" used instead of "type" (resp. "class") -
yet "object type", of course. Under "object" alone I'd understand an instance.
Perhaps, I have the German terminology mixed in a little, but that's what I'm
used to. Anyway, it's just words...

Quote
> > > I would like it to be something like;
> > > function IsAssociation (What : ObjectType) : boolean;

> > I guess you need two parameters here, or would this be a method?

> It's a method, implemented in the parent object for all other objects
> (classes...).

Then it would be alright (syntactically).
BTW, if you have a parent class (which is usual), then of course all classes
would be "associated", at least remotely...

Quote
> > > I've been trying lot's of things with VMT access and
> > > VMT links low-low-low-level things. But there must
> > > be a way of doing it!!!

> > I needed this myself several times... I fear it's impossible. :-( One o=
> f the
> > many weaknesses of TP's object concept - besides the "strange" scoping
> > ("Private"), that I'd rather call a bug, and other things...
> > (Btw, does Delphi address this problem - anyone knows?)

> Private fields isn't very spooky. The scope thing works as follows;
> pivate fields are
> accessable in the current unit, but not outside it. It must be this way
> if Borland don't
> use some "friend"-C-thing.

I know how it works, and I don't like it! When I say "private", I mean really
private to this very class. Of course, I'd also need "protected" for child
classes. There may also be a need for "friends", though I haven't found that
need too often (and when, I made the relevant things public and commented them
appropriately, like I have to do with the protected things). Anyway, I don't
find it very senseful to assume that all friends are in the same unit, and
everything in this unit are friends...

At last, your comment shows me a little bit of reason for this kind of
scoping - up to now I haven't seen any reason behind the limitation to units.

But still, I think you'd agree, the scoping is far from perfect, and much
worse than in C++.

Quote
> > I could think of a solution requiring registering each class with its p=
> arent
> > (I guess you know how to do that), but that's quite inconvenient...
> > If you require registering because of streams or so, this might not be =
> too
> > much more overhead - but still unhandsome...

> Yes, I've seen that solution in some programs. But, as you say, it's a
> bit ugly
> and I am a bit pedantic about these things. But, when a method inside
> a object calls it's parent object by the following code;

>    Inherited SomeMethodFromParent;

> The object must know the address of the parent method. Therefor, the
> parent
> must internally be known for Borland Pascal. The question is; how is it
> known?
> What is the link between the parent VMT and the object's VMT? =

No, I fear the connection is know only at compile time, not at runtime.
AFAIK, "Inherited Method" calls are compiled to absolute calls to the parent's
method. At runtime, the information about the parent seems simply not
available. I'm not absolutely sure about it, but like you I've tried much
(also thought about using "Inherited" somehow), but didn't find anything...

- Show quoted text -

Quote
> All these VMT things is a bit fuzzy. I've tried the following approach
> to
> the "find parent" dilemma;

>     1. Go to the VMT start address
>     2. Walk forward passed the two size fields (negsize and size)
>     3. Compare objects VMT method links (pointers) until a NIL pointer
> is
>        found (must be done since I don't know where the VMT ends).
>     4. If at least one link was equal, the objects is associated in some
> way.

> This is very primitive, since it not works always (at least one virtual
> method
> must not be overridden by the child obj.), and also allows _any_
> association.
> It would be better with strict association, ie. TRUE only if objects are
> directly
> inherited out of each other.

These are exactly the problems!

But wait... there's something...
Note: The following (probably) only applies to v7.0!

I was surprised about that nil pointer you mentioned. I didn't know of that.
When I tried it, I found that it isn't there! What you saw was the pointer
to the dynamic VMT (terminology?). Since you probably don't use dynamic
methods (actually, I don't think there's much use to them, except TV's/OWL's
event handling, what they've obviously been designed for), the pointer was
nil in your cases.

However, you can make something out of that. If you require that each class
declares (at least) one dynamic method, you can solve your problem, since each
DMT contains a pointer to its parent's DMT.

If a class doesn't declare a new dynamic method, it will use the same DMT as
its parent. So there's still that requirement, but at least you can check for
"strict association".

As another advantage, you could use this index that the dynamic method must
get as an index for the class, as for storing (like TStreamRec.ObjType in TV).

You could also put some other class data in this pseudo procedure, to address
another problem of BP, namely that of missing class variables (resp.
constants), like:

type TMyClass
  procedure MyClassInfo; virtual $4E;
end;

procedure TMyClass.MyClassInfo; assembler;
asm
  db 'MyClass',0 {Descriptor}
  db True        {Cloneable}
  ...            {other, class specific info}
end;

Just fantasizing... (of course, you'd have to make sure this layout is the
same with all classes...)

Surely, this is far from perfect, but you can't make a bad language (bad, of
course, only in this regard!) good by programming in that language. And
Borland will not make the language better, at least not under the name Pascal.

Followup to another part of this thread:

Quote
> >   function IsAssociation(what: ObjectType): Boolean;
> >   begin
> >    IsAssociation := (TypeOf(Self)=TypeOf(what)) OR
> >      inherited_object.IsAssociation(what)
> >   end;

> > Let me know if this works (or even better, if you find a better way...)

Looks nice. But...
a) You need a termination condition, i.e. implement it without the "inherited"
   branch for the top class.

b) Instead of "Typeof(Self)" you'd have to write "Typeof(<this class>)" with
   the consequence that you have to write the method for each class.
   And in that case, it would be easier IMHO (and probably more
   efficient) to register the classes with their parents...

Quote
> Your idea is very interesting. But it doesn't seem to work. Pretend
> that you've got a object hierarchy like

>       a --- b
>          |
>          +-- c - d

> If you call IsAssociation in b with d as a parameter, it won't
> return TRUE, because objects are nested. But if one extrapolate
> your idea slightly one could make a method like;

Now, I don't know what you want. I thought from the above that you wanted it
to return False since b and d are not directly inherited out of each other.
If you want to check any association, and have a general parent class, I
suggest the following: const IsAssiociation=True;-)

Quote
> procedure a.IsAssociation (What : ObjectPointerType) : boolean;
> begin
>     What := (TypeOf(Self) = TypeOf(What^)) or
>             Inherited IsAssociation (What) or
>             (What^.IsInitialized and What^.IsAssociation(@Self));
> end;

> But this I believe will not work either, beacuse it's endless
> recursion (how do you know when to stop checking the called object).

In the last line you'd have to go to the parent of "What". Then it would
always terminate. But, as said above, I don't see a sense in this kind of
checking.

Quote
> Also I am sceptical to the TypeOf operator. Are you really sure
> that TypeOf returns TRUE when used with Inherited.

No, it doesn't. Therefore b) above!

Quote
> Isn't the type of
> "self" equal when compared in "IsAssociation" and "Inherited
> IsAssociation"? Self should always be of the same type?!

Yes!

Quote
> But I don't think it's impossible to do this association thing.
> If you compare VMTs and use a modified IsAssociation, it
> could would should work. :-/

I still don't see a way. The main problem is, you don't seem to get a
reference (somehow) to the parent class without explicitly coding it for
each class. The compiler simply doesn't seem to generate such references
(except the DMT stuff), though they'd be quite useful...
However, if you do find something out, let me know!

Frank

Quote
> PS. Please forward answers to my mail address; j...@ts.umu.se. Also

BTW: No email forwarding necessary for me...

Other Threads