BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

A virtual class method was overriden?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Joao Morais
Guest





PostPosted: Fri Feb 09, 2007 6:41 pm    Post subject: A virtual class method was overriden? Reply with quote



Hello,

I need to verify if a virtual method was overriden, something like this:

TBaseClassClass = class of TBaseClass;

TBaseClass = class
class function Metadata: string; virtual;
end;

TImplementClass = class(TBaseClass)
class function Metadata: string; override;
end;

TNonimplementClass = class(TBaseClass)
end;

....

method(AClass: TBaseClassClass);
begin
if not (AClass has your _own_ Metadata implementation) then
...

A virtual class that returns an empty string isn't enough because:

TBaseClass = class
Metadata <<- returns ''

TSomeClass = class(TBaseClass)
Metadata <<- returns 'some metadata'

TProblematicClass = class(TSomeClass)
no metadata implementation, so TSomeClass.Metadata would be called.

If I'd implement the method in every class I'd solve the problem, I am
just trying to check if such method was really implemented.

Hints?

Thanks,
--
Joao Morais
Back to top
Ivo Bauer
Guest





PostPosted: Fri Feb 09, 2007 7:08 pm    Post subject: Re: A virtual class method was overriden? Reply with quote



Hi Joao,

Joao Morais napsal(a):
Quote:
A virtual class that returns an empty string isn't enough because:

TBaseClass = class
Metadata <<- returns ''

TSomeClass = class(TBaseClass)
Metadata <<- returns 'some metadata'

TProblematicClass = class(TSomeClass)
no metadata implementation, so TSomeClass.Metadata would be called.
If I'd implement the method in every class I'd solve the problem, I am
just trying to check if such method was really implemented.

Well, I'm sure you already knew that, but one can force *every*
descendant of a given ancestor class to implement a virtual method if
it's declared as abstract. Given your example class hierarchy listed
above, if TSomeClass overrides TBaseClass.GetMetadata abstract method,
there is however no way (at least that I know of) to force
TProblematicClass to provide its own implementation of this method. If
you want to be (for any reason) sure that TProblematicClass provides
its own implementation of GetMetadata method, make it descend directly
from TBaseClass.


--
Ivo Bauer [OZM Research]
Back to top
Ivo Bauer
Guest





PostPosted: Fri Feb 09, 2007 7:21 pm    Post subject: Re: A virtual class method was overriden? Reply with quote



Ivo Bauer napsal(a):
Quote:
If you want to be (for any reason) sure that TProblematicClass provides its
own implementation of GetMetadata method, make it descend directly from
TBaseClass.

But if it makes more sense to descend TProblematicClass from
TSomeClass rather than from TBaseClass, then I can't see anything
inherently wrong with the fact that the inherited implementation of
TSomeClass.GetMetadata method would be actually called if this method
is not overridden in TProblematicClass. It's just the way how it
works, or am I missing anything?


--
Ivo Bauer [OZM Research]
Back to top
Joao Morais
Guest





PostPosted: Fri Feb 09, 2007 8:06 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Ivo Bauer wrote:

Quote:
but one can force *every* descendant of a given ancestor class
to implement a virtual method if it's declared as abstract.

But you will be able to compile. Anyway this is valid only to the first
descendant class, not to the descendant of the descendant.

Quote:
If you want to be (for any reason) sure that TProblematicClass
provides its own implementation of GetMetadata method, make it descend
directly from TBaseClass.

I cannot do that. This was a sample, the real TProblematicClass need to
inherits the TSomeClass stuff.

Quote:
But if it makes more sense to descend TProblematicClass from TSomeClass
rather than from TBaseClass, then I can't see anything inherently wrong
with the fact that the inherited implementation of
TSomeClass.GetMetadata method would be actually called if this method is
not overridden in TProblematicClass. It's just the way how it works,

Right, my implementation is an exception.

Quote:
or am I missing anything?

Any metadata string is related with only one class. No parents, no
descendants, only that class. Something like RTTI. The metadata method
describes what that class implements, if it implements something. If
not, it should return '' instead of the parent's metadata.

This is part of a framework, I am just trying to work around some users'
omissions.

Thanks,
--
Joao Morais
Back to top
Ivo Bauer
Guest





PostPosted: Fri Feb 09, 2007 9:00 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Joao Morais napsal(a):
Quote:
Ivo Bauer wrote:

but one can force *every* descendant of a given ancestor class
to implement a virtual method if it's declared as abstract.

But you will be able to compile.

Sure, it would not cause compiler to emit an error but as soon as the
runtime code calls that method on instance of class that does not
provide actual implementation, EAbstractError exception will be raised.

Quote:
Anyway this is valid only to the first
descendant class, not to the descendant of the descendant.

Actually this is valid only for the first descendant class that
provides its own implementation of that method (even empty). It does
not necessarily be the first/direct descendant. Smile But I see your
point. I should have expressed myself more clearly.

Quote:
Any metadata string is related with only one class. No parents, no
descendants, only that class. Something like RTTI. The metadata method
describes what that class implements, if it implements something. If
not, it should return '' instead of the parent's metadata.

This is part of a framework, I am just trying to work around some users'
omissions.

OK. What about stripping this metadata stuff off your TBaseClass
altogether and implement some kind of (global) metadata registration
system:

type
TBaseClass = class of TMyBaseObject;

procedure RegisterClassMetadata(AClass: TBaseClass; const AMetaData:
string);
procedure UnregisterClassMetadata(AClass: TBaseClass);
function FindClassMetadata(AClass: TBaseClass): string;

There could be a global list of TClassMetadataItem instances holding
information about all registered classes, but this list will not be
accessible outside the unit where it would be declared. Instead it
will be manipulated by the above mentioned helper methods
(RegisterClassMetadata, ...):

type
TClassMetadataItem = class
public
ClassRef: TBaseClass;
Metadata: string;
end;

Every new (direct or indirect, it doesn't matter) descendant of
TBaseClass should be registered into this system. In your code you can
then easily check if a given class has been registered by calling
FindClassMetadata function which would return EmptyStr if it could not
find requested information. If that happens, simply raise an exception
indicating that the metadata info was not registered for given class
and it will be the responsibility of the one who developed such class
to take care of the registration/unregistration.

You can even make these global routines a class methods of TBaseClass:

TBaseClass = class
public
class procedure RegisterClassMetadata(const AMetaData: string);
class procedure UnregisterClassMetadata;
class function FindClassMetadata(AClass: TBaseClass): string;
end;

initialization
TMyProblematicClass.RegisterClassMetadata('my metadata');
finalization
TMyProblematicClass.UnregisterClassMetadata;

What do you think?


--
Ivo Bauer [OZM Research]
Back to top
Peter Morris
Guest





PostPosted: Fri Feb 09, 2007 10:02 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Quote:
Sure, it would not cause compiler to emit an error

When you create an instance of a class containing abstract methods the
compiler does emit a warning though.



--
Pete

Blessed are the geek, for they shall public class GeekEarth : Earth {}
====
Audio compression components, DIB graphics controls, ECO extensions,
FastStrings : http://www.droopyeyes.com
My blog : http://mrpmorris.blogspot.com
Back to top
Ivo Bauer
Guest





PostPosted: Fri Feb 09, 2007 10:12 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Peter Morris napsal(a):
Quote:
Sure, it would not cause compiler to emit an error

When you create an instance of a class containing abstract methods the
compiler does emit a warning though.

Correct, but IINM the compiler cannot detect cases when such class
instance is created via class reference, e.g.:

type
TMyBaseClass = class of TMyBaseObject;

TMyBaseClass = class end;
TMyConcreteClass = class(TMyBaseClass);

function CreateMyClassInstance(AClass: TMyBaseClass): TMyBaseClass;
begin
Result := AClass.Create;
end;


--
Ivo Bauer [OZM Research]
Back to top
Joao Morais
Guest





PostPosted: Fri Feb 09, 2007 10:21 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Ivo Bauer wrote:

Quote:
Anyway this is valid only to the first descendant class, not to the
descendant of the descendant.

Actually this is valid only for the first descendant class that provides
its own implementation of that method (even empty). It does not
necessarily be the first/direct descendant. Smile But I see your point. I
should have expressed myself more clearly.

Yup. It really wasn't what I said but it was what I meant.

Quote:
Any metadata string is related with only one class. No parents, no
descendants, only that class. Something like RTTI. The metadata method
describes what that class implements, if it implements something. If
not, it should return '' instead of the parent's metadata.

This is part of a framework, I am just trying to work around some
users' omissions.

OK. What about stripping this metadata stuff off your TBaseClass
altogether and implement some kind of (global) metadata registration
system:

/snip/

What do you think?

This is exactly what my first approach does and it is available yet. The
problem is that the metadata string is implemented far from the rest of
the class stuff -- ie a bit more difficult code to maintain when you
prefer to don't use the expert. Because of that I implemented the
virtual class approach as well. It is the perfect option for me,
provided that the metadata method is implemented in *all* classes.

--
Joao Morais
Back to top
Peter Morris
Guest





PostPosted: Fri Feb 09, 2007 10:41 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Quote:
Correct, but IINM the compiler cannot detect cases when such class
instance is created via class reference, e.g.:

type
TMyBaseClass = class of TMyBaseObject;

TMyBaseClass = class end;
TMyConcreteClass = class(TMyBaseClass);

function CreateMyClassInstance(AClass: TMyBaseClass): TMyBaseClass;
begin
Result := AClass.Create;
end;

Probably not, no. If that is what he is doing then that'll teach me for not
bothering to read the post properly Smile
Back to top
Les Pawelczyk
Guest





PostPosted: Sat Feb 10, 2007 12:57 am    Post subject: Re: A virtual class method was overriden? Reply with quote

Quote:
method(AClass: TBaseClassClass);
begin
if not (AClass has your _own_ Metadata implementation) then


procedure Test(AClass: TBaseClassClass);
var lfvM: function: string of object;
begin
lfvM := AClass.Metadata;
if TMethod(lfvM).Code = Addr(TBaseClass.Metadata)
then ShowMessage('not implemented')
end;



Les.
Back to top
Peter Below (TeamB)
Guest





PostPosted: Sat Feb 10, 2007 1:38 am    Post subject: Re: A virtual class method was overriden? Reply with quote

Joao Morais wrote:

Quote:

Hello,

I need to verify if a virtual method was overriden, something like
this:

TBaseClassClass = class of TBaseClass;

TBaseClass = class
class function Metadata: string; virtual;
end;

TImplementClass = class(TBaseClass)
class function Metadata: string; override;
end;

TNonimplementClass = class(TBaseClass)
end;

...

method(AClass: TBaseClassClass);
begin
if not (AClass has your own Metadata implementation) then
...

A virtual class that returns an empty string isn't enough because:

TBaseClass = class
Metadata <<- returns ''

TSomeClass = class(TBaseClass)
Metadata <<- returns 'some metadata'

TProblematicClass = class(TSomeClass)
no metadata implementation, so TSomeClass.Metadata would be called.

If I'd implement the method in every class I'd solve the problem, I
am just trying to check if such method was really implemented.


Display('TBaseclass.Metadata: %p', [@TBaseclass.Metadata]);
Display('TImplementclass.Metadata: %p', [@TImplementClass.Metadata]);
Display('TNonImplementclass.Metadata: %p',
[@TNonImplementClass.Metadata]);

Shows:
TBaseclass.Metadata: 0045EC34
TImplementclass.Metadata: 0045EC44
TNonImplementclass.Metadata: 0045EC34

The problem is that this scheme only works with explicite classnames,
since the compiler needs to be able to resolve the address at compile
time. If you have a class reference in a variable typed as the base
classes class the compiler will refuse to evaluate
an expression of the the form @classvar.Metadata. But you can work
around that using a method pointer type.

type
TBaseClass = class
class function Metadata: string; virtual;
end;

TBaseCLassCLass = class of tbaseclass;
TProc = function : string of object;

TImplementClass = class(TBaseClass)
class function Metadata: string; override;
end;

TNonimplementClass = class(TBaseClass)
end;

procedure TForm1.Button1Click(Sender: TObject);
var
bcc: TBaseclassclass;
proc: TProc;
begin
Display('TBaseclass.Metadata: %p', [@TBaseclass.Metadata]);
Display('TImplementclass.Metadata: %p', [@TImplementClass.Metadata]);
Display('TNonImplementclass.Metadata: %p',
[@TNonImplementClass.Metadata]);
bcc := TImplementclass;
proc := bcc.Metadata;
Display('bcc.Metadata: %p', [@proc]);
end;

That gives

TBaseclass.Metadata: 0045ED38
TImplementclass.Metadata: 0045ED48
TNonImplementclass.Metadata: 0045ED38
bcc.Metadata: 0045ED48

So, the solution to your problem is to construct a method pointer for
TBaseclass.Metadata, another for the class you want to examines (even
if it is held in a class reference var), and then compare the two
pointers. If they are equal the class at hand does not override the
method, if they are different the method was overriden.

--
Peter Below (TeamB)
Don't be a vampire (http://slash7.com/pages/vampires),
use the newsgroup archives :
http://www.tamaracka.com/search.htm
http://groups.google.com
http://www.prolix.be
Back to top
Joao Morais
Guest





PostPosted: Sat Feb 10, 2007 2:28 am    Post subject: Re: A virtual class method was overriden? Reply with quote

Les Pawelczyk wrote:

Quote:
method(AClass: TBaseClassClass);
begin
if not (AClass has your _own_ Metadata implementation) then


procedure Test(AClass: TBaseClassClass);
var lfvM: function: string of object;
begin
lfvM := AClass.Metadata;
if TMethod(lfvM).Code = Addr(TBaseClass.Metadata)
then ShowMessage('not implemented')
end;

Perhaps this another piece of code will give what I need:

function ImplementsMetadataMethod(AClass: TBaseClassClass): Boolean;
var
vm1, vm2: function: string of object;
begin
if AClass <> TBaseClass then
begin
vm1 := AClass.Metadata;
vm2 := TBaseClassClass(AClass.ClassParent).Metadata;
Result := TMethod(vm1).Code <> TMethod(vm2).Code;
end else
Result := True;
end;

You and Peter Below solved the trick, thank you very much!

--
Joao Morais
Back to top
Joao Morais
Guest





PostPosted: Sat Feb 10, 2007 2:30 am    Post subject: Re: A virtual class method was overriden? Reply with quote

Peter Below (TeamB) wrote:

Quote:
So, the solution to your problem is to construct a method pointer for
TBaseclass.Metadata, another for the class you want to examines (even
if it is held in a class reference var), and then compare the two
pointers. If they are equal the class at hand does not override the
method, if they are different the method was overriden.

Your approach is very close to the Les' one, comments are there. Thank
you very much for your comments and tests.

--
Joao Morais
Back to top
David M
Guest





PostPosted: Sat Feb 10, 2007 9:13 am    Post subject: Re: A virtual class method was overriden? Reply with quote

Hi Joao

Quote:

TBaseClassClass = class of TBaseClass;

TBaseClass = class
class function Metadata: string; virtual;
end;

TImplementClass = class(TBaseClass)
class function Metadata: string; override;
end;

TNonimplementClass = class(TBaseClass)
end;

If your function is published and your class emits RTTI (e.g. compiled

with M+ or descends from TPersistent) then you will have a published
MethodTable in the class's VMT at the vmtMethodTable offset. You can
scan through this to see if the method is included or not. Take a
look at the GetMethodInfo to see how to proceed.

All other static and virtual methods (whether overridden or not) will
appear in the class's VMT method listing so you can't check this to
determine if it has been overridden.

Another option is to declare the base method as dynamic and then check
the dynamic method table. Beware of the performance implications of
dispatching dynamic methods though.

HTH

D
David Moorhouse
Moorhouse Works ltd
www.moorhouse.co.nz
Back to top
Ivo Bauer
Guest





PostPosted: Sat Feb 10, 2007 8:43 pm    Post subject: Re: A virtual class method was overriden? Reply with quote

Joao Morais napsal(a):
Quote:
This is exactly what my first approach does and it is available yet. The
problem is that the metadata string is implemented far from the rest of
the class stuff -- ie a bit more difficult code to maintain when you
prefer to don't use the expert. Because of that I implemented the
virtual class approach as well. It is the perfect option for me,
provided that the metadata method is implemented in *all* classes.

I know that you already have the solution you were asking for but I'm
still in the wondering mode myself. Smile Could you please reveal some
more details about those metadata and what they're used for in your
framework? I don't know for sure, but it seems to me that from the
design point of view they have no relation to the base class (and
their descendants) themselves but rather to the way how these classes
are treated and managed by your framework. If this is the case then it
might be a good idea to separate the metadata handling from the class.
But I may be wrong, of course. :-)

Any ideas/comments?


--
Ivo Bauer [OZM Research]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.