Polymorphism and casts.

Started by
3 comments, last by KuroSei 12 years, 1 month ago
Greetings again.

I tumbled across another problem which seems to be quite huge:
I registered an Interface from C++, named 'BaseEntity'.
A script class "AbstractBaseEntity" inherits that Interface.
A script class "AbstractNPC" inherhits "AbstractBaseEntity"

That results in a rather simple class hierarchy...


So far, so good.
I also have registered a method 'instanciate' for a global property named System. It works well, and instanciates my entities just fine. It is registered to return a handle '@BaseEntity' ... which works fine, too.
I can use the InterfaceSpecific methods then.

But now comes the clue:
I cant cast!

The following code does not work:


// Those are self designed includes. They work fine. I made a scriptdump to verify right behavior.
#include scripts/entity/IBaseEntity.as
#include scripts/entity/NPC.as

void main() {
// System pretty sure is registered. But check to be sure... :P
if( System is null ) {
println("System is null.Aborting.");
return;
}

// Instanciate an entity.
BaseEntity@ ent=System.instanciate("AbstractBaseEntity");

if (ent !is null) {
println("Received Entity(BaseEntity) with id: "+ent.getID());
} else {
println("Ent is null... :'( ");
}


// Prints:
AbstractBaseEntity@ ent2=cast<AbstractBaseEntity>(ent);
if (ent2 !is null)
println("We have an AbstractBaseEntity at hand, btw.");


// Works fine.
ParamList par();
par.addParam("TestNPC");
BaseEntity@ ent3=System.instanciate("AbstractNPC","AbstractNPC @AbstractNPC(int,string)",par);

//ent3 is an BaseEntity by now. Its true. I checked it. (:

AbstractNPC@ ent4=cast<AbstractNPC>(ent);
if (ent4 !is null)
println("We have an AbstractNPC at hand, btw.");


}


Prints:
Received Entity(BaseEntity) with id: 0
AbstractNPC created. ( <- This is printed in the constructor of AbstractNPC )



I just updated to the newst version of angelscript. So far everything seems to work fine.
Help appreciated.

With warm regards,
Kuro Sei.

PS: Shall i have missed some important details or in case you need some closer specification of my registrations or the script classes i will update those asap. But for now i dont see any reasyon why i should pump up this overextended wall of text even more.
Advertisement
Classes compiled in different modules by default get different type ids, even if they are compiled from the same source code. This means that they are completely different from one another, even though they have the same name. I suspect this is what is happening in your code above.

Your application is probably instanciating an AbstractNPC class compiled in module "A" and then passes a handle to it to module "B" where the main() function is. If this is the case then that is why the cast doesn't work.

In order for a class to have the same type across different modules it must be declared as 'shared'. The same goes for interfaces. By declaring the interface and the class as shared, you're telling the script compiler that they are meant to be transferred between modules. The compiler will then make sure the class/interface doesn't use anything that is specific to one module, e.g. global variables or other types that are not shared.

Interfaces registered from the application are always shared.

You declare interfaces, classes, functions, and enums as shared by prepending the declaration with the keyword 'shared'


shared class AbstractBaseEntity : BaseEntity
{
}

shared class AbstractNPC : AbstractBaseEntity
{
}


A non-shared class can inherit from a shared class or interface, but a shared class cannot inherit from a non-shared class or interface.

Manual: Shared script entities

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I knew there was the shared keyword.
I did not know that the same class in different modules has different type ids. But now that you explained it it sounds indeed logical. I feel stupid again. ):

Thanks a lot, andreas, again.
I dont know which god blessed you, but he is a hella good one. :P

Still i ask myself if the import keyword couldnt be extended to allow importation of Classes, too. I think it would be a nice alternative for using shared.
I'm happy to help.


The import functionality is on the brink of being deprecated. It don't feel it work as well as it should.

In the future I will most likely implement something similar to what other modern languages do with regards for using code from other modules. But it will take a different form than the current import functionality.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Glad to hear that.
So long i will stick with the solution i got now. It works like a charm!

This topic is closed to new replies.

Advertisement