• Advertisement
Sign in to follow this  

AngelScript - polymorphism, interfaces, and inheritance

This topic is 4339 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've finally decided the solution that I'll adopt for AngelScript in regards to script declared classes with inheritance, polymorphism, etc. I will go the Java way, with only single inheritance and interfaces, as it is much easier to implement and get to work correctly. The C++ way that allow single, multiple, and virtual inheritance, is too complicated for the scripted environment. The syntax will be similar to Java as well:
interface MyInterface
{
  void SomeFunction();
  int  AnotherFunction();
};

class A
{
  A()                   {} 
  void FuncFromA()      {}
};

class B : A, MyInterface // inherits from A, implements interface MyInterface
{
  B()                   {}
  FuncFromA()           {} // overloads the function from class A
  void SomeFunction()   {} // implements the interface function
  int AnotherFunction() {} // implements the interface function
};

void function()
{
  B obj;

  A a = obj;             // OK, only the base class information is copied
  MyInterface @i = obj;  // OK, the handle for obj is taken, but interpreted as the interface
  i.SomeFunction();      // Calls obj.SomeFunction();
  obj.FuncFromA();       // Calls obj.FuncFromA() that overloads A.FuncFromA()
}


The application will be able to specify an interface that it expects, which will allow the scripts to declare classes that implements this interface and pass instances of that script class to the application function. Normal C++ classes cannot implement the script interfaces, as they will simply not be compatible with the way AngelScript handles the interfaces. However, hopefully I'll be able to allow the application to implement C++ classes that inherits from an asCScriptObject class defined by the library, which can then be registered with the same functionality as the script declared classes. If all goes well the scripts will also be able to inherit from these special C++ classes. I'm just telling you a bit about the near future of AngelScript, so that you can comment on it, and perhaps help me detect any flaws before I get too far into the implementation. Regards, Andreas

Share this post


Link to post
Share on other sites
Advertisement
Will it differentiate between public, private, and protected inheritence?

Also, some random advice you're free to ignore, and I don't really know how to express the idea. I see that this can go two ways: you can implement just enough to allow us to extend polymorphic heirarchies in script, which I assume is what most people are going to want to do, or you can get horribly bogged down in making everything work perfectly. Angelscript is getting more and more powerful. I just want to remind you to remember what the library is for, and make it the best at that, instead of turning it into a general purpose language that's okay at everything but not great at anything.

Share this post


Link to post
Share on other sites
To start with everything will be public, but if it becomes necessary in the future, adding this access restriction should be a rather simple matter.

I agree with you on being careful with turning AngelScript into a general purpose language, with only okay results. I certainly do not want to do that, and please let me know if you think that I'm going too far with the features.

I feel that classes without polymorphism are quite useless, so the interfaces are a necessary feature. Inheritance is less important, in my opinion, since you're usually not writing huge projects in scripts and can in most cases simply duplicate the necessary code. Single inheritance is almost free though, so I decided to support that. Multiple inheritance, and even more so virtual inheritance, is much more complicated and expensive. With the current design they are not even possible to implement, which is one more reason why I decided to go with Java way.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Hi Andreas,
I think the classes are great since they make many things easier. Inheritance is also OK. But I personally don't need polymorphism or interfaces. I'm also a little bit concerned that that might be a little bit to much for a scripting language. I just think that sometimes less is more and one of the big strengths of AngleScript is that the library is so light weight. But that's just my opinion so please don't take it to serious.

By,
Martin

Share this post


Link to post
Share on other sites
I have to disagree with Cheetah3D.. polymorphism can be a really helpful tool. Consider the scenario where enemy entities are defined in scripts: enemies could be implemented by deriving from a common enemy class and implementing different behaviours.

I'm not saying this is the only way to do this - given the dynamic nature of scripting, one can easily map different scripts to each enemy type with, say, a set of functions with different implementations and I would probably adopt the latter approach to keep things simple.

I do agree however that polymorphism may be too complex a notion for level designers, despite being a neat solution. Having said that, there are other scenarios that justify the existense of polymorphism in a script and in some cases may be the most feasible approach.

Share this post


Link to post
Share on other sites
Don't worry people, the inheritance and interfaces shouldn't add too much overhead for AngelScript, and while they are not always needed, they really can be a great tool for simplifying the programming tasks.

AngelScript will continue to be light-weight, but it should also be flexible enough to let the application developer solve his problems in the way he feels most comfortable, whether that be through using only global functions, or classes with polymorphism.

I have plans to use compile time flags for disabling support for various features, in order to allow the application to use an even more light-weight version of AngelScript. Though, this in itself can be difficult to do, so we'll have to wait and see how well this works.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Just wondering, can a method be non-virtual? And if so, can someone please explain when that is wanted/needed/useful? I've always thought polymorphism was what made OO so powerful..

Share this post


Link to post
Share on other sites
You do not want all of your methods to be virtual as there is a certain cost in looking up the function address from the vtable.

You don't always need all of your objects to be polymorphic either.

Share this post


Link to post
Share on other sites
If you're using inheritance, I cannot think of any reason why you wouldn't want to use virtual methods. But as Rain Dog said, virtual methods have a slight performance overhead, so if you don't need them, you shouldn't use them.

However, I'm not sure if I'll use non-virtual methods in AngelScript yet. I do not think the overhead that virtual methods incurr will be noticeable in the script language. If I can do without the non-virtual methods, the language will be cleaner and less confusing for script developers. But we'll see about this in the future.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Non virtual functions have different lookup rules, for one thing. Examine the following example...


class A
{
public:
virtual void foo() {}
void bar() {}
};

class B : public A
{
public:
virtual void foo() {}
void bar() {}
};

A* an_a = new A();
an_a->foo(); //calls A::foo
an_a->bar(); //calls A::bar

B* a_b = new B();
a_b->foo(); //calls B::foo
a_b->bar(); //calls B::bar (or it might actually be an ambigous...)

an_a = a_b; //implicit downcast
an_a->foo(); //calls B::foo
an_a->bar(); //calls A::bar


Share this post


Link to post
Share on other sites
You're correct. But can you think of any situation where it would be useful not to declare the method as virtual in the base class when you're overloading it in the derived class?

Quote:

an_a->bar(); //calls A::bar, but an_a is pointing to a B instance which overloads the bar() method


I can't think of any situation where the above behaviour would actually be useful.

Share this post


Link to post
Share on other sites
well, you might not even want virtual calls.

You might want.

class A
{
protected:
string name;
public:
string get_Name(){return name;}
string set_Name(string N){name = n;}

class B : public A
{
.. code
}

B b;
b.set_Name("my new name");

Share this post


Link to post
Share on other sites
also, I think multiple inheritance is cool and interfaces are cop-outs.

The decision then is does MI really belong in script language. I think that it would be nice.

Share this post


Link to post
Share on other sites
I know that if you're not doing any overloading of methods then you shouldn't declare the methods as virtual. But this is not my doubt, my doubt is when would you want to _not_ declare a method as virtual but still want to overload it.

I have a chance to leave it up to the compiler whether to automatically declare a method as virtual or not. It would then declare all methods that are overloaded as virtual and thus save the script writer from having to worry about that. This is of course assuming that it would never be necessary to have non-virtual methods that are still overloaded.

I too think that multiple inheritance can be useful in some cases and it doesn't incur much overhead for C++. The way the script classes work however, it wouldn't be as easy to implement, and it would incur a much larger overhead. Maybe in the future I'll find a better solution for the script class, that would make multiple inheritance possible, but at the moment I won't even try it.

Regards,
Andreas

Share this post


Link to post
Share on other sites
In java, interface methods cannot have definitions. Would it be too hard to get around this, but keep it similar otherwise?

It's one thing that bugs me about java interfaces, it seems it's preferable to make something an interface so that types that derive from another superclass can use it.

But in doing so you lose out the "code reuse" part of OO, because you cannot give definitions to these methods in the interface.

If I'm making some sense let me know.

Share this post


Link to post
Share on other sites
Allowing implementations in the declaration of the interfaces would effectively make it multiple inheritance.

With interfaces, the derived class doesn't actually inherit anything, not even virtual methods. The interfaces is only a way to tell the compiler that the class is guaranteed to have that set of methods, so that the object can be passed to a function that needs to call those methods on the object.

The code reuse can be solved in other ways than inheritance. You could for example use mix-in, which is what the D language does. Macros is another way that works.

Share this post


Link to post
Share on other sites
It's important to remember that public inheritence - what allows for polymorphism - is NOT a tool for code re-use in C++. It models an 'is-a' relationship between the derived and parent classes. Code re-use calls for an 'is-implemented-in-terms-of' relationship, and would use private inheritence or containment.

In short, your argument about Java's 'strange' limitations on interface classes is flawed because your understanding of the concept they represent is flawed.

Share this post


Link to post
Share on other sites
Quote:
Original post by Deyja
It's important to remember that public inheritence - what allows for polymorphism - is NOT a tool for code re-use in C++. It models an 'is-a' relationship between the derived and parent classes. Code re-use calls for an 'is-implemented-in-terms-of' relationship, and would use private inheritence or containment.

In short, your argument about Java's 'strange' limitations on interface classes is flawed because your understanding of the concept they represent is flawed.


Oh no. I thought code reuse meant reusing code. Sorry for my very stupid post.

Change may statement to be about "reusing code" instead.

Any complaints now?

@WitchLord

I confess to not using angel script, but depending on how you will implement virtual methods (hence my comment: "Would it be too hard to get around this" ) I can't see this being impossible.

Maybe its just me, but I think most of the problems in multiple inheritance come from the memory layout of the objects, particularly when passing them as one of their super types.

I mean, if you go the vtable way, you will need to know which method in an object corresponds to the ones in the interface anyway...

Share this post


Link to post
Share on other sites
I'm not planning on using vftables to resolve the interface methods, exactly because of the problem with the memory layout question due to multiple inheritance. I'll use something slower, but easier to implement to start with. Maybe in the future I'll look for a faster solution, if it's worth it.

I'll probably use vftables for the virtual methods inherited through single inheritance though, as this is the fastest and easiest way to do it.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Quote:
Any complaints now?


Yes. You totally failed to see the point I made. Go read it again.

Share this post


Link to post
Share on other sites
Sounds good to me! I used to be a huge fan of mulitple inheritance but since being forced to work on java games for work I don't even use it anymore even in c++ apps. Sometimes it can be good, but honestly there is nothing that multiple inheritance lets you do which you can't do another way. Like any language feature its a tool that can be used but it shouldn't become a crutch which your code relies on. If its hard todo as well as adding alot of overhead to AS then I say leave it out - I won't miss it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement