On 23 Apr 2003 at 11:47, Frank Heckenbach wrote:
[...]
Ignoring the index would make a dynamic method the same as a virtual method. This can be somewhat useful (with appropriate health warnings) when porting existing code (i.e., GPC accepts the syntax, but the meaning would be different).
Depends. For "normal" usage (without this dispatching) it would be the same AFAICS.
Correct.
From what I can see the real usefulness of dynamic methods (apart from alleged savings in memory) lies in the index. BP uses this for its message dispatching mechanisms in the OWL framework (although this is probably at library level rather than at compiler level). Delphi can use it as well. I have sorely missed this feature when trying to build an OWL-compatible OOP framework, and have had to find klugdes round it. A simple example; type foo = object (tfoo) procedure cmSave (var m : tmessage); virtual cm_Save; end;
What this means in BP/Delphi is that when the menu or button (or whatever) with the integer ID of cm_Save is selected/clicked, etc., then run the method "cmSave". Obviously there is a message dispatch mechanism involved, in order for anything to know that cm_Save has been clicked/selected.
Having now written all this, I am starting to wonder as to its relevance as it seems clear that this has nothing to do with the compiler per se ;-/
I think there are different ways how to implement such a dispatcher:
a)
case ID of ... cm_Save: cmSave (m); ... end;
This is what I have done/am doing in my OOP framework (slightly similar to Borland's OWL framework). But it involved a number of extra steps and kludges which are not necessary in BP or Delphi. It was actually do-able without any major grief.
This is plain (OOP) Pascal, and would work with normal virtual methods, and therefore also with "dynamic" ones if GPC just ignores the index.
b)
Using some magic that looks up the dynamic method index in some internal table to do the call.
The disadvantages of b) are that it requires more compiler magic, and that it might be type-unsafe (if the method is looked up at runtime, there's no way for the compiler to check the parameter list -- unless all dynamic methods are required to have the same parameters).
In BP OWL and Delphi VCL code, they all seemed to involve a parameter "(Var Message : TMessage)" - but may well be a result of the message dispatching protocols involved in the respective OOP frameworks. If you tried this in OWL without having that parameter, you always got a GPF (aka segfault, stackdump, or whatever corresponds on other systems). The GPF may well be a sign of the type- unsafeness that you talk about (i.e., it is up to the programmer to get it right). Personally, I think that is a small price to pay - but others will probably disagree.
The only advantages I can see are that it might save a few bytes in memory (which is most likely a non-issue today and probably it was even back then), and that it may have been faster at runtime than a `case' statement in BP. However, GPC/GCC optimizes `case' much better, using jump tables when useful, so that's probably no issue, either.
Then, it's a little effort to write the `case' statement, but that's mostly a one-time job I think (and can probably be added to existing BP code locally), so I'd suggest this.
Unfortunately, my experience with building an OOP framework showed that it is far more involved than a simple case statement. I basically had to invent my own message dispatching mechanisms. These involved case statements, but that was only the end of the process. It may well be however that, for normal programming, this wouldn't be the case, and it would just be a matter of a simple case statement.
Be that as it may, simply supporting the syntax would be good enough, and I would be happy with whatever direction you choose to go.
Best regards, The Chief --------- Prof. Abimbola Olowofoyeku (The African Chief) Web: http://www.bigfoot.com/~african_chief/