Started by Monsieur OUXX, 06 Sep 2021, 16:47

« previous - next »

Monsieur OUXX

I'm experimenting with the old discovery of monkey0506 that polymorphism is somewhat possible. He explained it here : https://www.adventuregamestudio.co.uk/wiki/Extender_Methods_mean_Polymorphism!

What I've done :

Code: ags

managed struct Base {
import int GetSetting(this Base*);

managed struct A extends Base {
import int GetSetting(this A*);

managed struct B extends Base {
import int GetSetting(this B*);

Code: ags

int GetSetting(this Base*)
   AbortGame("You need to overwrite this function");

int GetSetting(this A*)
   return 666;

int GetSetting(this B*)
   return 777;

Then I do this :
Code: ags

Base* array[10];
array[0] = new A;
array[1] = new B;

So far so good. I've managed to store instances of both A and B into the same array of Base.

My issue is that I don't know how to cast back.

If I do this :
Code: ags

Base* o = array[0];
o.GetSetting(); //This causes AbortGame because it calls Base::GetSetting instead of A::GetSetting

And if I do this :
Code: ags

A* o = array[0]; //The compiler forbids this. It doesn't know how to cast back from Base* to A*

Do you have an idea to make polymorphism work? Something like GUIControl::AsLabel or GUIControl::AsButton.
If I try to write this I'll encounter the same issue as before :
Code: ags

A* AsA(this Base*)
    return this; //AGS won't know how to cast from Base to A.

Crimson Wizard

Don't have time for a good reply right now, but some time ago I commented on this very article when it was suggested to be added to the new manual (I thought it's not structured well enough and may be confusing to users).

Something I'd like to copy here is this paragraph:

If we look into theory, there's static or compile-time polymorphism and dynamic or run-time polymorphism. Now, AGS script formally does not support either by itself. This text explains how to achieve kind of static polymorphism (I think?) for a very specific case using extenders. Dynamic polymorphism and things like calling child-type implementation from a reference to parent type is not possible in AGS without scripting that yourself, and it's more complicated than, say, in C, where you do not have "classes" but may have pointers to functions allowing you to create virtual tables by hand...

I may expand on this if find time later.

PS. Oh, and one of the potential consequences of adding RTTI feature would be dynamic pointer type casting from parent to child.

Monsieur OUXX

Ok then, thank you. I understand the ins and outs of AGS inner workings, but I'm really interested in a practical solution.

What I understand by "casting to child type is not possible unless you do it yourself" is "you must do it through something similar to monkey's example: create a new instance of the child type and manually 'recreate' it by starting off the parent's data and passing child-specific data". I understand.

SMF spam blocked by CleanTalk