I am looking at ObjAsm32's example01A:

The example has a Shape object derived from Primer.
Two objects derive from Shape: TriangleShape and RectangleShape.
The last one (RectangleShape) defines and implements a method TestFunction
This TestFuncion is overridden by Rectangleshape.IsQuad at run time.

What puzzles me:
IsQuad¦nbsp; is not in the object definition of RectangleShape, nor in one of it's ancestors.
Then how can IsQuad be in the implemention section of RectangleShape?
Shouldn't an implemented method always be in the objects definition section too?

Friendly regards,
mdevries.
Posted on 2006-07-11 15:02:52 by mdevries
Hi mdevries
In this subject there are 2 points of interest. First, RectangleShape.TestFunction is a dynamic method, that means that any change (overriding) you make will only affect a particular instance of RectangleShape. In our case, this is pShape_2. If we would have a second instance, let’s say pShape_3 of RectagleShape, this is not affected by the overriding!
This is the particularity of dynamic methods. The trick is that these methods are not handled using the standard VMT. Their method address is stored in the instance itself!
StaticMethods are different in this sense, since their addresses are stored in the VMT that are common for all instances of a given object.

Now to your question (second point), all methods can be overridden at runtime with another method which can be defined somewhere in the code. It is not necessary that the new method is placed in the same .inc or .asm file. I.e. it can be in another module or even in a DLL that you load at runtime. The only requirement for the new method is that it has the same formal parameters as the overridden method.

There are some little special things that you will discover when using some features. If you can’t see behind the scenes immediately, simply ask!  ;)

Biterider
Posted on 2006-07-11 16:10:14 by Biterider
Hi Biterider,

As I understand: IsQuad doesn't have a type (Static or Dynamic) of itself.
When a method is overridden by IsQuad, it depends on the type of the method that is overridden, whether it will be used statically or dynamically.

And is this correct:
As used in example01A you can't call IsQuad directly, since it is not in the object definition.
You can only use it to override another method with, and then call it using the other methods name.

Friendly regards,
mdevries.
Posted on 2006-07-11 16:37:07 by mdevries
Hi mdevries
As I understand: IsQuad doesn't have a type (Static or Dynamic) of itself.

Correct.

As used in example01A you can't call IsQuad directly, since it is not in the object definition.

Correct. You can't call this method using OCall/ACall/ICall... But, since it is code defined somewhere, you can execute it jumping to or calling it (i.e. using invoke and providing all arguments).

Regards,

Biterider
Posted on 2006-07-12 00:22:36 by Biterider
Hi Biterider,

Correct. You can't call this method using OCall/ACall/ICall... But, since it is code defined somewhere, you can execute it jumping to or calling it (i.e. using invoke and providing all arguments).


If you use invoke, would it's first parameter be the Self parameter?
Because the documentation says:

The Method macro hides the Self (instance) pointer, which is always passed as first argument.



I have another question on Override. The documentation on Override says:

Override
The reserved word Override is used to redefine a static or dynamic method at run-time.
Redefining a static method will affect all instances of the object, while redefining a dynamic method only affects a specific object instance.


In example01A it is a DynamicMethod that is overridden. So, that works.

I tried and tried, but could not produce an example of an Override on a StaticMethod. It's always the original method that is called.
Can you produce a working example of an overridden StaticMethod?


Friendly regards,
mdevries.
Posted on 2006-07-13 05:20:44 by mdevries
Hi mdevries
In fact, you can call a method using invoke (previous versions of OA32 did it this way), passing Self as first parameter. Example:

invoke RectangleShape_GetArea, pSHape_2

In this case it is equivalent to

OCall pShape_2::RectangleShape.Getarea

OCall and co. are more powerful in the OOP context than invoke. They handle automatically a variable amount of parameters (Methods defined with a “???? at the end of the parameter declaration; see the Array object)

I found a bug in the Objects.inc file that didn’t let you to override static methods. I attached the corrected version and a little example that works. Thanks for pointing it out. ;)

Regards,

Biterider
Posted on 2006-07-13 14:39:18 by Biterider
Hi Biterider,

Thanks for your support, and the update.
It works.

Friendly regards,
mdevries.
Posted on 2006-07-13 16:58:21 by mdevries
Hi Biterider,

Still a few questions on Override.

I did some more tests on an Overriden StaticMethod, in order to become more familiar with the specific behaviour of Override.

I created 3 objects, that inherit from each other:
- Object1 is the ancestor.
  - Object2 is a descendant of Object1.
      - Object3 is a descendant of Object2.

Object1 defines and implements Method1 which is a StaticMethod.
Object2 redefines Method1.
Object3 redefines Method1 too.
Object3 also defines Method2, which can be used for overriding another method.
Object3 also defines Method3, which can be used for overriding Method2

Creating an instance of Object3 gives us 3 different implementations of Method1.
- Object1.Method1
- Object2.Method1
- Object3.Method1

Due to the polymorphic capabilities of OCall a call to one of these methods will endup in a call to Object3.Method1.

But what method would be called if we perfom ONE of the following methods?

Override pObject::Object1.Method1,Object3.Method2
Override pObject::Object2.Method1,Object3.Method2
Override pObject::Object3.Method1,Object3.Method2


After one of these Overrides, we perform all of the three following calls:

OCall pObject::Object1.Method1
OCall pObject::Object2.Method1
OCall pObject::Object3.Method1


All these calls have the same result:
Object3.Method2 is called.

Conclusion:
If we do a runtime override in an ancestor on a method which is also defined in a descendant, and we call it in the descendant, the override prevails.

Example:
Override pObject::Object2.Method1,Object3.Method2
OCall pObject::Object3.Method1


This will call Object3.Method2, NOT Object3.Method1.

Do we really want the override of Object2.Method1 to prevail?
Is this the behaviour you had in mind?

--------------------------------------------
I also tested a double (chained) override:

Override pObject::Object2.Method1,Object3.Method2
Override pObject::Object3.Method2,Object3.Method3

OCall pObject::Object2.Method1


This will call Object3.Method2, NOT Object3.Method3

Changing the order of the Overrides doesn't make any difference:

Override pObject::Object3.Method2,Object3.Method3
Override pObject::Object2.Method1,Object3.Method2

OCall pObject::Object2.Method1


This will also call Object3.Method2

Can't chaining of Overrides be considered Polymorfic?

Friendly regards,
mdevries.
Posted on 2006-07-14 11:57:44 by mdevries
Are you aware of the ACall macro?
Even if you override a Method of an Ancestor class, you can still call it if you want to.. which can be handy in some situations.
Posted on 2006-07-14 13:42:37 by Homer
Hi Homer,

Yes, I am aware of the ACall method.
In that case you don't want to call the method in the search level, but you want to call a method implemented at a higher level (in an ancestor of the mentioned level).

Example:
If you perform an ACall on Object3 you don't want the method implemented in Object3 to be performed, but you want the nearest higher implemented method with the same name to be performed.

In my previous post the opposite is the case.
You don't want to perform a call on an ancestor.
You want a call on the mentioned level, or even polymorphically deeper, if the method is implemented on an even deeper level too.

This is the specific situation I mention in my previous post:

Object1 --> Object2 --> Object3
              |        ^
              V        |
          Override    OCall


A StaticMethod is polymorphic, so an OCall should always call the method on the deepest level, it can find an implementation of the method on.

Consider this:
OCall pObject::Object2.Method1


The search start should be in Object2, searching downwards, until it finds the deepest level of implementation.
But the search seems to start in Object1, goes polymorphically downwords, until it finds an Override, and that's the end. So, due to the override of the method in Object2, it will never find the method in Object3, or deeper.

Friendly regards,
mdevries.
Posted on 2006-07-14 14:26:05 by mdevries
Hi mdevries
The observations of your experiments are all correct.
A little bit more light will give a look at the Override macro.
The first argument is the key to understand what happens. The instance pointer is used here to locate the VMT (or more properly DMT – dual method table) that is associated to this instance. The following object name is used (in a polymorphic way) to tell the compiler what object layout to use and finally the method name that is resolved together with the layout to give an relative offset to the DMT.

Now if pObject3 is of type Object3, you are changing this DMT, not that of Object2.
To achieve this use something like

Override pObject2.Object2.xxx, xxx

Another way is to use the Object templates (@Objectname). The location in memory can be found using the offset operator. I attached an example to this post.

I hope it clarifies the behaviour of the Override macro.  8)

Regards,

Biterider
Posted on 2006-07-14 16:33:05 by Biterider
Thanks again for a new example.

In ObjAsm32 Usage chapter of the documentation under the header "Method Calls" following is stated:

In many cases, when you have overridden a dynamic method,
you would call the original method.
This is possible using a call to the object's template where the
original method address is stored:

TCall esi::Shape.GetArea

On static methods, a TCall has no effect, since an OCall executes
a TCall for this type of methods.


My conclusion was: It must be possible to perform a TCall on a dynamic method.

Well, I am able to do a TCall on a static method, but when I do a TCall on a dynamic method I get a compilation error:

error A2052: forced error : Methodtype not recognized.


The next part in the documentation says:

In other situations you'll need to call the method of a direct
ancestor. This is usually the case in constructor and destructor
methods. You can achieve it by calling:

ACall esi::Shape.GetArea

In this example, this sentence calls the Prime's Done destructor
method.

ACall executes a TCall on the ancestor's template. This way,
if the ancestor's method is a dynamic method that was overridden,
ACall uses the original method stored in the template!


There's a small typo here: GetArea is called, which is not the Prime's Done destructor.

Apart from that this part of the documentation gave me the idea that it should be able to perform an ACall on a DynamicMethod.

I tested an ACall on a StaticMethod and onother on a DynamicMethod.
- The ACall to the StaticMethod was succesfull
- The ACall to the DynamicMethod was not succesfull: An exception followed.

Is the documentation correct?
Or is something wrong with the TCall and/or ACall macro?
Or am I disoriented???

Friendly regards,
mdevries.
Posted on 2006-07-15 03:25:35 by mdevries
Hi mdevries
ACall / TCall issue on dynamic methods fixed. Example added at the end of this post.
Typo on help file also fixed. Thanks! ;)

Regards,

Biterider
Attachments:
Posted on 2006-07-15 16:51:52 by Biterider
Thanks again,

I compared the output of the exe, shipped in the zip file, with te source files. I think you slightly modified your project without building a new exe, before putting it in the zip file.

Rebuild the project, and you get a slightly different output.
But Never mind. I just mention it, in case you intend to roll it out in a new version.

Friendly regards,
mdevries.
Posted on 2006-07-15 17:21:58 by mdevries
Hi
Yes, it possible... I was playing with the code changing the GetArea method from static to dynamic and back again to see what happens. You will see a commented out line in the Shape object definition. It's good to exercise it to see the output and to understand where the pointers are changed.

Thanks for your comments. They are all appreciated!

Regards,

Biterider
Posted on 2006-07-15 23:28:03 by Biterider
Hi Biterider,

As you can see in this thread:

ACall/TCall on a dynamic method didn't work, so the "ObjAsm32 community" has never used it.
The same can be said for the Override on a static method: It has never been used.

Besides ICall, the community usually uses:
- BoundMethods (that can't be overridden),
- OCall and ACall on StaticMethods,
- Override on a DynamicMethod (never on a StaticMethod).

So, all my comments are just marginal: Nobody seems to feel the need to use it.
Nevertheless, your product has improved again: If they want, they can use it now.

I tried nothing in the COM field yet. So I don't know what will happen there.

Friendly regards,
mdevries.
Posted on 2006-07-16 03:45:08 by mdevries
That's fairly accurate, I *did* use some runtime overrides of static methods in my IOCP server framework, but that was a rather unusual architecture.
In general, I tend to avoid dynamic methods since they make my instances larger than they would otherwise be.
In fact, I tend to avoid overriding methods at runtime, period.
The only reason for this is that normally I find runtime overrides to be unnecessary, I simply haven't had many situations which required them.
Posted on 2006-07-16 04:07:40 by Homer